-
1. 入門
-
2. Git 基礎
-
3. Git 分支
-
4. 伺服器上的 Git
- 4.1 協定
- 4.2 在伺服器上取得 Git
- 4.3 產生您的 SSH 公開金鑰
- 4.4 設定伺服器
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方託管選項
- 4.10 總結
-
5. 分散式 Git
-
A1. 附錄 A:其他環境中的 Git
- A1.1 圖形介面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 總結
-
A2. 附錄 B:在您的應用程式中嵌入 Git
-
A3. 附錄 C:Git 命令
7.9 Git 工具 - Rerere
Rerere
git rerere
功能是一個有點隱藏的功能。這個名稱代表「重複使用記錄的解析」,顧名思義,它允許您要求 Git 記住您如何解析一個程式碼塊衝突,以便下次它看到相同的衝突時,Git 可以自動為您解決。
在許多情況下,此功能可能會非常方便。文件中提到的一個例子是,當您想要確保一個長期存在的主題分支最終會順利合併,但您不希望一堆中間合併提交混亂您的提交歷史時。啟用 rerere
後,您可以嘗試偶爾合併,解決衝突,然後退出合併。如果您持續這樣做,則最終合併應該很容易,因為 rerere
可以自動為您完成所有操作。
如果您想要保持分支變基,這樣您就不必每次都處理相同的變基衝突,也可以使用相同的策略。或者如果您想要取得一個您合併並修復了一堆衝突的分支,然後決定改為變基,您可能不必再次執行所有相同的衝突。
rerere
的另一個應用是您偶爾將一堆正在演變的主題分支合併到一個可測試的標頭中,就像 Git 專案本身經常做的那樣。如果測試失敗,您可以倒回合併並重新執行它們,而無需重新解決衝突。
要啟用 rerere
功能,您只需執行此配置設定
$ git config --global rerere.enabled true
您也可以在特定儲存庫中建立 .git/rr-cache
目錄來開啟它,但是配置設定更清楚,並且為您全域啟用該功能。
現在讓我們看一個簡單的範例,類似於我們之前的範例。假設我們有一個名為 hello.rb
的檔案,看起來像這樣
#! /usr/bin/env ruby
def hello
puts 'hello world'
end
在一個分支中,我們將單字「hello」更改為「hola」,然後在另一個分支中,我們將「world」更改為「mundo」,就像之前一樣。

當我們將兩個分支合併在一起時,我們會得到一個合併衝突
$ git merge i18n-world
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Recorded preimage for 'hello.rb'
Automatic merge failed; fix conflicts and then commit the result.
您應該注意到其中的新行 Recorded preimage for FILE
。否則它應該看起來像一個正常的合併衝突。此時,rerere
可以告訴我們一些事情。通常,您可能會在此時執行 git status
以查看所有衝突
$ git status
# On branch master
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add <file>..." to mark resolution)
#
# both modified: hello.rb
#
但是,git rerere
也會使用 git rerere status
告訴您它已記錄了哪些合併前狀態
$ git rerere status
hello.rb
而 git rerere diff
將顯示解析的當前狀態,也就是您開始解析的狀態以及您解析後的狀態。
$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,11 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
+<<<<<<< HEAD
puts 'hola world'
->>>>>>>
+=======
+ puts 'hello mundo'
+>>>>>>> i18n-world
end
另外(這與 rerere
無關),您可以使用 git ls-files -u
來查看衝突的檔案以及之前、左側和右側的版本
$ git ls-files -u
100644 39804c942a9c1f2c03dc7c5ebcd7f3e3a6b97519 1 hello.rb
100644 a440db6e8d1fd76ad438a49025a9ad9ce746f581 2 hello.rb
100644 54336ba847c3758ab604876419607e9443848474 3 hello.rb
現在你可以將其解決為僅僅是 puts 'hola mundo'
,然後你可以再次運行 git rerere diff
來查看 rerere 將記住什麼。
$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,7 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
- puts 'hola world'
->>>>>>>
+ puts 'hola mundo'
end
這基本上表示,當 Git 在 hello.rb
檔案中看到一個區塊衝突,其中一邊是 “hello mundo”,另一邊是 “hola world” 時,它將會將其解決為 “hola mundo”。
現在我們可以將其標記為已解決並提交。
$ git add hello.rb
$ git commit
Recorded resolution for 'hello.rb'.
[master 68e16e5] Merge branch 'i18n'
你可以看到它顯示「為 FILE 記錄解決方案」。

現在,讓我們撤銷該合併,然後將其變基到我們的 master
分支之上。我們可以像在揭秘 Reset 中看到的那樣,使用 git reset
將我們的分支移回。
$ git reset --hard HEAD^
HEAD is now at ad63f15 i18n the hello
我們的合併已撤銷。現在讓我們變基主題分支。
$ git checkout i18n-world
Switched to branch 'i18n-world'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: i18n one word
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Resolved 'hello.rb' using previous resolution.
Failed to merge in the changes.
Patch failed at 0001 i18n one word
現在,我們得到了與預期相同的合併衝突,但請注意「使用先前的解決方案解決 FILE」這一行。如果我們查看該檔案,我們會看到它已經被解決了,其中沒有合併衝突標記。
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
此外,git diff
將會向你展示它是如何自動重新解決的。
$ git diff
diff --cc hello.rb
index a440db6,54336ba..0000000
--- a/hello.rb
+++ b/hello.rb
@@@ -1,7 -1,7 +1,7 @@@
#! /usr/bin/env ruby
def hello
- puts 'hola world'
- puts 'hello mundo'
++ puts 'hola mundo'
end

你也可以使用 git checkout
重建衝突的檔案狀態。
$ git checkout --conflict=merge hello.rb
$ cat hello.rb
#! /usr/bin/env ruby
def hello
<<<<<<< ours
puts 'hola world'
=======
puts 'hello mundo'
>>>>>>> theirs
end
我們在進階合併中看到了一個範例。不過,現在讓我們再次執行 git rerere
來重新解決它。
$ git rerere
Resolved 'hello.rb' using previous resolution.
$ cat hello.rb
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
我們已經使用 rerere
快取的解決方案自動重新解決了該檔案。你現在可以添加並繼續變基以完成它。
$ git add hello.rb
$ git rebase --continue
Applying: i18n one word
因此,如果你進行大量的重新合併,或者想要在沒有大量合併的情況下使主題分支與你的 master
分支保持同步,或者你經常變基,你可以開啟 rerere
來幫助你更輕鬆一點。