Git reflog 引用日誌使用詳解

跡憶客發表於2021-12-30

本章節主要介紹 git reflog 命令。 Git 使用一種稱為引用日誌或“reflogs”的機制來跟蹤分支頂端的更新。 許多 Git 命令接受用於指定引用或“ref”的引數,它是指向提交的指標。 常見的例子包括:

Reflogs跟蹤本地倉庫中Git引用的更新時間。除了分支提示引用日誌之外,還為Git儲存維護了一個特殊的reflog。Reflogs儲存在本地倉庫的.git目錄中。git reflog目錄可以在.git/logs/refs/heads/ 和 .git/logs/HEAD找到,如果在倉庫中使用了git stash,還可以在.git/logs/refs/stash中找到。

本章節將介紹:git reflog的擴充套件配置選項、git reflog的常見用例和缺陷、如何使用git reflog撤消更改,等等。


git reflog 基本用法

下面是最基本的 reflog 用法

$ git reflog

 

 

這本質上是一個快捷方式,相當於:

$ git reflog show HEAD

 

這將輸出 HEAD reflog。 我們應該會看到類似於以下內容的輸出:

eb1050b (HEAD -> feature_branch) HEAD@{0}: checkout: moving from main to feature_branch
1525c48 (origin/main, main) HEAD@{1}: checkout: moving from 2bf1773d87a7806cda25d4d313995bb08adbabf5 to main
2bf1773 HEAD@{2}: commit: rebas
b71dc26 HEAD@{3}: rebase: 增加撤銷更改命令內容
31c9ba0 (origin/jiyik, jiyik) HEAD@{4}: rebase: checkout jiyik
eb1050b (HEAD -> feature_branch) HEAD@{5}: commit: Adds new feature
1525c48 (origin/main, main) HEAD@{6}: checkout: moving from main to feature_branch
1525c48 (origin/main, main) HEAD@{7}: commit (merge): 解決衝突

 


Reflog 引用

預設情況下, git reflog 將輸出 HEAD ref 的 reflog。 HEAD 是對當前活動分支的符號引用。 引用日誌也可用於其他引用。 訪問 git ref 的語法是 name@{qualifier}。 除了 HEAD 引用,其他分支、標籤、遠端和 Git 儲存也可以被引用。

可以通過執行以下命令獲取所有引用的完整引用日誌:

$ git reflog show --all 

 

要檢視特定分支的引用日誌,請將該分支名稱傳遞給 git reflog show

$ git reflog show jiyik

 

 

執行上面的命令將顯示 jiyik 分支的引用日誌。 


定時的reflog

每個 reflog 條目都有一個時間戳。 這些時間戳可以用作 Git 引用指標語法的限定符標記。 這可以按時間過濾 Git 引用日誌。 以下是可用時間限定符的一些示例:

  • 1.minute.ago
  • 1.hour.ago
  • 1.day.ago
  • yesterday
  • 1.week.ago
  • 1.month.ago
  • 1.year.ago
  • 2011-05-17.09:00:00

時間限定符可以組合(例如 1.day.2.hours.ago),此外還接受複數形式(例如 5.minutes.ago)。

時間限定符 refs 可以傳遞給其他 git 命令。

$ git diff main@{0} main@{1.day.ago} 

 

此示例將當前 main 分支與 1 天前的 main 分支進行比較。 如果想知道某個時間範圍內發生的更改,此示例非常有用。


git reflog 子命令和配置選項

git reflog 接受一些被視為子命令的附加引數。

Show - git reflog show

show 預設是隱式傳遞的。 例如下面命令:

$ git reflog main@{0} 

 

 

和下面的命令是等價的

$ git reflog show main@{0}

 

另外,git reflog show 是 git log -g --abbrev-commit --pretty=oneline 的別名。

Expire - git reflog expire

expire 子命令清除舊的或無法訪問的 reflog 條目。 expire 子命令有可能丟失資料。 這個子命令通常不被終端使用者使用,而是由 git 內部使用。將 -n 或 --dry-run 選項傳遞給 git reflog expire 將執行“試執行”,它將輸出哪些 reflog 條目被標記為要修改,但實際上不會修改它們。

預設情況下,reflog 到期日期設定為 90 天。 可以通過將命令列引數 --expire=time 傳遞給 git reflog expire 或通過設定 gc.reflogExpire 的 git 配置名稱來指定過期時間。

Delete - git reflog delete

delete 子命令是不言自明的,將刪除傳入的 reflog 條目。 與 expire 一樣,delete 有可能丟失資料,並且通常不會被終端使用者呼叫。


恢復丟失的提交

Git 永遠不會真正丟失任何東西,即使在執行歷史重寫操作(例如重新設定基準或提交修改)時也是如此。 對於下一個示例,讓我們假設我們對我們的倉庫進行了一些新的更改。 我們下面命令檢視日誌資訊 

$ git log --pretty=oneline
338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content 
1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content 
c49257493a95185997c87e0bc3a9481715270086 flesh out intro 
eff544f986d270d7f97c77618314a06f024c7916 migrate existing content 
bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline 
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs 

 

然後我們提交這些更改並執行以下操作:

$ git commit -am "some WIP changes" 

 

在這一點上,我們通過執行下面的命令進入互動模式

$ git rebase -i origin/main 

 

在rebase過程中,我們使用s rebase子命令將提交標記為擠壓。在rebase期間,我們將一些提交壓縮到最近的“some WIP changes ”提交中。

因為我們壓縮了提交,git日誌輸出現在看起來像:

40dhsoi37656e19d4e4f1a9b419f57850ch87dah987698hs some WIP changes 
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs 

 

如果我們此時檢查 git log ,似乎我們不再有標記為壓縮的提交。 如果我們想對壓縮的提交之一進行操作怎麼辦? 從歷史中刪除它的變化? 此時就可以使用 git reflog 。

$ git reflog
37656e1 HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog 
37656e1 HEAD@{1}: rebase -i (start): checkout origin/main 
37656e1 HEAD@{2}: commit: some WIP changes 

 

我們可以看到 rebase 的開始和結束有 reflog 條目,在這些條目之前是我們的“some WIP changes ”提交。 我們可以將 reflog 引用傳遞給 git reset 並重置為 rebase 之前的提交。

$ git reset HEAD@{2} 

 

執行此重置命令會將 HEAD 移動到新增了“some WIP changes”的提交,實質上是恢復其他壓縮的提交。


git reflog 總結

在本教程中,我們討論了 git reflog 命令。涵蓋的一些關鍵點是:

  • 如何檢視特定分支的 reflog
  • 如何使用reflog撤銷 git rebase
  • 如何指定和檢視基於時間的 reflog 記錄

我們簡要提到 git reflog 可以與其他 git 命令一起使用,例如 git checkoutgit reset 和 git merge。 在各自章節中瞭解更多知識點。

相關文章