簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-rerere 上次更新於 2.39.0

名稱

git-rerere - 複用衝突合併的已記錄解決方案

概要

git rerere [clear | forget <pathspec>…​ | diff | status | remaining | gc]

描述

在採用相對長期的主題分支的工作流中,開發者有時需要反覆解決相同的衝突,直到主題分支完成(無論是合併到“釋出”分支,還是傳送並被上游接受)。

此命令透過記錄衝突的自動合併結果和相應的初始手動合併的手動解決結果,並將之前記錄的手動解決方案應用於其相應的自動合併結果,從而協助開發者完成此過程。

注意
您需要設定配置變數 rerere.enabled 以啟用此命令。

命令

通常,git rerere 在不帶引數或使用者干預的情況下執行。但是,它有幾個命令允許其與其工作狀態進行互動。

clear

如果合併解決方案將被中止,則重置 rerere 使用的元資料。呼叫 git am [--skip|--abort]git rebase [--skip|--abort] 將自動呼叫此命令。

forget <路徑規範>

重置 rerere 為 <路徑規範> 中當前衝突記錄的衝突解決方案。

diff

顯示解決方案當前狀態的差異。它對於跟蹤使用者解決衝突時發生的變化很有用。附加引數直接傳遞給安裝在 PATH 中的系統 diff 命令。

status

列印 rerere 將記錄其合併解決方案的衝突路徑。

remaining

列印尚未被 rerere 自動解決的衝突路徑。這包括 rerere 無法跟蹤其解決方案的路徑,例如衝突的子模組。

gc

修剪很久以前發生的衝突合併記錄。預設情況下,超過 15 天未解決的衝突和超過 60 天已解決的衝突將被修剪。這些預設值分別透過 gc.rerereUnresolvedgc.rerereResolved 配置變數控制。

討論

當您的主題分支修改了自其從 master 分支(或上游)派生以來,master 分支(或上游)已觸及的重疊區域時,您可能希望用最新的 master 進行測試,即使您的主題分支尚未準備好推送到上游。

              o---*---o topic
             /
    o---o---o---*---o---o master

為了進行此類測試,您需要以某種方式合併 master 和主題分支。一種方法是將 master 拉取到主題分支中。

	$ git switch topic
	$ git merge master

              o---*---o---+ topic
             /           /
    o---o---o---*---o---o master

標有 * 的提交觸及同一個檔案中相同區域;您需要在建立標有 + 的提交時解決衝突。然後您可以測試結果,以確保您的進行中工作仍然適用於最新的 master 中的內容。

在這次測試合併之後,有兩種方法可以繼續在主題分支上工作。最簡單的方法是在測試合併提交 + 之上構建,當您的主題分支中的工作最終準備好時,將主題分支拉取到 master 中,和/或請求上游從您這裡拉取。然而,到那時,master 或上游可能自測試合併 + 以來已推進,在這種情況下,最終的提交圖將如下所示:

	$ git switch topic
	$ git merge master
	$ ... work on both topic and master branches
	$ git switch master
	$ git merge topic

              o---*---o---+---o---o topic
             /           /         \
    o---o---o---*---o---o---o---o---+ master

然而,當您的主題分支是長期存在的,您的主題分支最終會包含許多此類“來自 master 的合併”提交,這會不必要地混淆開發歷史。Linux 核心郵件列表的讀者可能還記得,當子系統維護者請求從一個充滿“無用合併”的分支拉取時,Linus 抱怨過這種過於頻繁的測試合併。

作為替代方案,為了使主題分支不受測試合併的干擾,您可以放棄測試合併,並繼續在測試合併之前的頂端之上構建。

	$ git switch topic
	$ git merge master
	$ git reset --hard HEAD^ ;# rewind the test merge
	$ ... work on both topic and master branches
	$ git switch master
	$ git merge topic

              o---*---o-------o---o topic
             /                     \
    o---o---o---*---o---o---o---o---+ master

當您的主題分支最終準備好併合併到 master 分支時,這將只留下一個合併提交。此合併將要求您解決由標有 * 的提交引入的衝突。然而,此衝突通常與您放棄的測試合併時解決的衝突相同。git rerere 幫助您使用早期手動解決方案的資訊來解決這個最終的衝突合併。

在衝突自動合併後立即執行 git rerere 命令會記錄衝突的工作樹檔案,其中包含常見的衝突標記 <<<<<<<=======>>>>>>>。稍後,在您解決完衝突後,再次執行 git rerere 將記錄這些檔案的已解決狀態。假設您在將 master 測試合併到主題分支時執行了此操作。

下一次,在看到相同的衝突自動合併後,執行 git rerere 將在較早的衝突自動合併、較早的手動解決方案和當前衝突自動合併之間執行三方合併。如果此三方合併乾淨地解決,結果將寫入您的工作樹檔案,因此您無需手動解決。請注意,git rerere 不觸及索引檔案,因此當您滿意時,您仍然需要使用 git diff(或 git diff -c)和 git add 進行最終健全性檢查。

作為一項便利措施,git merge 在因自動合併失敗退出時會自動呼叫 git rerere,並且 git rerere 在是新衝突時記錄手動解決方案,或在不是新衝突時複用較早的手動解決方案。git commit 在提交合並結果時也會呼叫 git rerere。這意味著您無需自己做任何特殊操作(除了啟用 rerere.enabled 配置變數)。

在我們的示例中,當您進行測試合併時,手動解決方案被記錄下來,並且只要記錄的解決方案仍然適用,它將在您稍後使用更新的 master 和主題分支進行實際合併時被複用。

git rerere 記錄的資訊在執行 git rebase 時也會被使用。在放棄測試合併並繼續在主題分支上開發之後

              o---*---o-------o---o topic
             /
    o---o---o---*---o---o---o---o   master

	$ git rebase master topic

				  o---*---o-------o---o topic
				 /
    o---o---o---*---o---o---o---o   master

您可以執行 git rebase master topic,以便在您的主題分支準備好傳送到上游之前更新自己。這將導致回退到三方合併,並且它將以與您之前解決的測試合併相同的方式發生衝突。git rerere 將由 git rebase 執行以幫助您解決此衝突。

[注意] git rerere 依賴於檔案中的衝突標記來檢測衝突。如果檔案已包含看起來與帶有衝突標記的行相同的行,git rerere 可能無法記錄衝突解決方案。為了解決此問題,可以使用 gitattributes[5] 中的 conflict-marker-size 設定。

GIT

Git[1] 套件的一部分

scroll-to-top