1. 程式人生 > >使用git reflog 命令來檢視歷史提交記錄並使用提交記錄恢復已經被刪除掉的分支

使用git reflog 命令來檢視歷史提交記錄並使用提交記錄恢復已經被刪除掉的分支

一、問題描述
昨天下午有個同事急急忙忙跑我座位上,要我幫忙,說他剛剛因為手誤,將他本地的某個project的某個branch分支刪除了,並且也將Gitlab上面的遠端分支也刪除了。他本來是想發起merge request的,但是後面他眼神不好以為已經merged過了,就直接刪了Gitlab上的遠端分支並且將他本地的這個分支也直接刪除了。

現在他跑過來問我有沒有辦法恢復,不然他這一天的工作就白費了。

看他急急忙忙不知所措的樣子,我直接調侃他說恢復不了。要他以後小心點刪除branch,不要眼神不好。後面才慢慢地然後使用了git reflog 查找了他所有的分支提交記錄等,然後找到對應的git commit的sha1碼,然後恢復過來了。他說居然還有這種操作,666!我去,這是常規操作好嗎?

所以 如何恢復本地和遠端倉庫都已經刪除掉的分支呢??下面我來演示一下。

二、復現問題
現在我準備找一個測試的demo git 工程來進行演練一下,如何恢復以及被刪除的分支。

1、建立一個git倉庫並且提交一個檔案


[email protected]207891 MINGW32 /f/git test
$ git init
Initialized empty Git repository in F:/git test/.git/

[email protected] MINGW32 /f/git test (master)
$ vim test.txt

[email protected]

MINGW32 /f/git test (master)
$ cat test.txt
11111111111111111111111111111111

[email protected] MINGW32 /f/git test (master)
$ git add .
warning: LF will be replaced by CRLF in test.txt.
The file will have its original line endings in your working directory.

[email protected] MINGW32 /f/git test (master)
$ git commit -m "first commit"
[master (root-commit) 363a197] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt

[email protected] MINGW32 /f/git test (master)
$ git branch
* master

[email protected] MINGW32 /f/git test (master)
$


2、再次編輯test.txt檔案並且提交


3、切換分支並再次編輯test.txt檔案並且提交
建立並切換到 feature/test1分支


在feature/test1分支上繼續編輯test.txt檔案並且提交


[email protected] MINGW32 /f/git test (master)
$ git checkout -b feature/test1
Switched to a new branch 'feature/test1'

[email protected] MINGW32 /f/git test (feature/test1)
$ git branch
* feature/test1
  master

[email protected] MINGW32 /f/git test (feature/test1)
$ git log
commit 77dfdffc87bde49a6361bbdf36a9b01a20c10a3b
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:38:44 2018 +0800

    second commit

commit 363a197ffb4236ec9d6ee5b7631ae326eae958f4
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:36:32 2018 +0800

    first commit

[email protected] MINGW32 /f/git test (feature/test1)
$ vim test.txt

[email protected] MINGW32 /f/git test (feature/test1)
$ cat test.txt
11111111111111111111111111111111


22222222222222222222222222222222


33333333333333333333333333333333

[email protected] MINGW32 /f/git test (feature/test1)
$ git add test.txt
warning: LF will be replaced by CRLF in test.txt.
The file will have its original line endings in your working directory.

[email protected] MINGW32 /f/git test (feature/test1)
$ git commit -m "third commit"
[feature/test1 dab39f4] third commit
 1 file changed, 3 insertions(+)

[email protected] MINGW32 /f/git test (feature/test1)
$ git log
commit dab39f4808f6553e57a0551f44044919a31dc76b
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:42:17 2018 +0800

    third commit

commit 77dfdffc87bde49a6361bbdf36a9b01a20c10a3b
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:38:44 2018 +0800

    second commit

commit 363a197ffb4236ec9d6ee5b7631ae326eae958f4
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:36:32 2018 +0800

    first commit

[email protected] MINGW32 /f/git test (feature/test1)
$
現在我們有兩個分支了,一個 feature/test1分支,一個 master分支。 feature/test1分支比master分支多了一次提交記錄。

4、刪除刪除 feature/test1 分支
現在我們模擬剛才那位同事之間刪除了 feature/test1 分支。我們先checkout到master分支,然後刪除 feature/test1 分支


feature/test1分支因為沒有合併到master分支,就被刪除了。所以此時master分支沒有feature/test1分支上做的新的修改記錄。


[email protected] MINGW32 /f/git test (feature/test1)
$ git checkout master
Switched to branch 'master'

[email protected] MINGW32 /f/git test (master)
$ git branch
  feature/test1
* master

[email protected] MINGW32 /f/git test (master)
$ git branch -d feature/test1
error: The branch 'feature/test1' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature/test1'.

[email protected] MINGW32 /f/git test (master)
$ git branch
  feature/test1
* master

[email protected] MINGW32 /f/git test (master)
$ git branch -D feature/test1
Deleted branch feature/test1 (was dab39f4).

[email protected] MINGW32 /f/git test (master)
$ git branch
* master

[email protected] MINGW32 /f/git test (master)
$ git log
commit 77dfdffc87bde49a6361bbdf36a9b01a20c10a3b
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:38:44 2018 +0800

    second commit

commit 363a197ffb4236ec9d6ee5b7631ae326eae958f4
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:36:32 2018 +0800

    first commit


三、恢復feature/test1分支
如何恢復feature/test1分支呢??

3.1 找到feature/test1分支的最後一次提交記錄
我們使用 git reflog 來看下git的提交記錄,可以發現 dab39f4這次提交記錄描述是 third commit 。

區別:如果在回退以後又想再次回到之前的版本,git reflog 可以檢視所有分支的所有操作記錄(包括commit和reset的操作),包括已經被刪除的commit記錄,git log則不能察看已經刪除了的commit記錄

[email protected] MINGW32 /f/git test (master)
$ git branch
* master

[email protected] MINGW32 /f/git test (master)
$ git log
commit 77dfdffc87bde49a6361bbdf36a9b01a20c10a3b
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:38:44 2018 +0800

    second commit

commit 363a197ffb4236ec9d6ee5b7631ae326eae958f4
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:36:32 2018 +0800

    first commit

[email protected] MINGW32 /f/git test (master)
$ git reflog
77dfdff [email protected]{0}: checkout: moving from feature/test1 to master
dab39f4 [email protected]{1}: commit: third commit
77dfdff [email protected]{2}: checkout: moving from master to feature/test1
77dfdff [email protected]{3}: commit: second commit
363a197 [email protected]{4}: commit (initial): first commit


我們再來看看之前的截圖,在feature/test1分支第三次提交的值為 dab39f4808f6553e57a0551f44044919a31dc76b


dab39f4 和 dab39f4808f6553e57a0551f44044919a31dc76b 不就是提交記錄的簡寫和完整的寫法,一模一樣。

因此我們找到了這次提交的SHA1校驗和,因此我們就可以恢復feature/test1分支了。

3.2 根據feature/test1分支的最後一次提交記錄來恢復feature/test1分支


[email protected] MINGW32 /f/git test (master)
$ git reflog
77dfdff [email protected]{0}: checkout: moving from feature/test1 to master
dab39f4 [email protected]{1}: commit: third commit
77dfdff [email protected]{2}: checkout: moving from master to feature/test1
77dfdff [email protected]{3}: commit: second commit
363a197 [email protected]{4}: commit (initial): first commit

[email protected] MINGW32 /f/git test (master)
$ git branch
* master

[email protected] MINGW32 /f/git test (master)
$ git checkout -b feature/test1 dab39f4
Switched to a new branch 'feature/test1'

[email protected] MINGW32 /f/git test (feature/test1)
$ git branch
* feature/test1
  master

[email protected] MINGW32 /f/git test (feature/test1)
$ git log
commit dab39f4808f6553e57a0551f44044919a31dc76b
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:42:17 2018 +0800

    third commit

commit 77dfdffc87bde49a6361bbdf36a9b01a20c10a3b
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:38:44 2018 +0800

    second commit

commit 363a197ffb4236ec9d6ee5b7631ae326eae958f4
Author: ouyangpeng <[email protected]>
Date:   Wed Nov 14 09:36:32 2018 +0800

    first commit

[email protected] MINGW32 /f/git test (feature/test1)
$


我們可以看到,我們恢復了 feature/test1分支,並且feature/test1分支之前的提交記錄都完整的還原回來了,和原來一樣,比master分支多了一次提交記錄。如下所示:


3.3 在Gitlab上根據commit SHA直接新建branch來恢復被刪除的分支
當然也可以在Gitlab上根據commit SHA直接新建branch來恢復被刪除的分支,操作如下所示:

選擇【Create from】,然後輸入剛才查詢到的commit SHA

然後點選回車


接著在【Branch name】寫上分支名即可恢復了。

四、git reflog 簡介
官方介紹地址 https://git-scm.com/docs/git-reflog

具體的操作以及選項可以去上面的官網檢視具體的用法,下面我就將剛才我們使用的git reflog 稍微講下即可。

4.1 檢視歷史版本記錄
命令:git reflog
作用:檢視提交版本歷史記錄
執行命令後如圖:


[email protected] MINGW32 /f/git test (feature/test1)
$ git reflog
dab39f4 [email protected]{0}: checkout: moving from master to feature/test1
77dfdff [email protected]{1}: checkout: moving from feature/test1 to master
dab39f4 [email protected]{2}: commit: third commit
77dfdff [email protected]{3}: checkout: moving from master to feature/test1
77dfdff [email protected]{4}: commit: second commit
363a197 [email protected]{5}: commit (initial): first commit

從圖中可以看到,執行git reflog 命令後,顯示出來了很多行記錄。

每行記錄都由版本號(commit id SHA),HEAD值和操作描述三部分組成。版本號在第一列,HEAD值在第二列,操作描述資訊在第三列。

版本號
在之前都有提到,標識著每一次提交、合併等操作時的版本,相當於唯一標識
HEAD值
同樣用來標識版本,但是不同於版本號的是,Head值是相對的。
當HEAD值為HEAD時,表示為提交的最新版本;HEAD^ 表示為最新版本的上一個版本;HEAD^^表示為最新版本的上上個版本;HEAD~100表示為最新版本的往上第100個版本。
HEAD值越小,表示版本越新,越大表示版本生成時間越久。

在上面圖中,我們發現HEAD值的展示形式為[email protected]{0}、[email protected]{1}、[email protected]{2}…同樣HEAD值的數字越小,表示版本越新,數字越大表示版本越舊。

操作描述
記錄了本次是哪種操作,以及操作時編寫的描述資訊。
4.2 檢視歷史版本記錄–指定顯示條數
同時,與git log相同的是,git reflog也提供了控制顯示條數的選項:
命令:git reflog -n
執行命令後如圖:


[email protected] MINGW32 /f/git test (feature/test1)
$ git reflog -3
dab39f4 [email protected]{0}: checkout: moving from master to feature/test1
77dfdff [email protected]{1}: checkout: moving from feature/test1 to master
dab39f4 [email protected]{2}: commit: third commit

[email protected] MINGW32 /f/git test (feature/test1)
$
如圖所示,這裡設定顯示條數為3條,執行命令後,顯示的條數為指定的條數3條。

[email protected] MINGW32 /f/git test (feature/test1)
$ git reflog -6
dab39f4 [email protected]{0}: checkout: moving from master to feature/test1
77dfdff [email protected]{1}: checkout: moving from feature/test1 to master
dab39f4 [email protected]{2}: commit: third commit
77dfdff [email protected]{3}: checkout: moving from master to feature/test1
77dfdff [email protected]{4}: commit: second commit
363a197 [email protected]{5}: commit (initial): first commit
如圖所示,這裡設定顯示條數為6條,執行命令後,顯示的條數為指定的條數6條。