Git

名稱

git-replay - 實驗性功能:在新的基礎上重播提交,也適用於裸儲存庫

概要

(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance <branch>) <revision-range>…​

描述

取得提交的範圍並將它們重播到新的位置。不會動到工作目錄和索引,也不會更新任何參考。此命令的輸出旨在用作 git update-ref --stdin 的輸入,這將更新相關的分支(請參閱下方的輸出章節)。

此命令為實驗性功能。行為可能會變更。

選項

--onto <newbase>

建立新提交的起點。可以是任何有效的提交,而不僅僅是現有的分支名稱。

當指定 --onto 時,輸出中的 update-ref 命令將更新修訂範圍中的分支,使其指向新的提交,類似於 git rebase --update-refs 更新受影響範圍內多個分支的方式。

--advance <branch>

建立新提交的起點;必須是分支名稱。

當指定 --advance 時,輸出中的 update-ref 命令將更新作為 --advance 引數傳遞的分支,使其指向新的提交(換句話說,這模仿了 cherry-pick 操作)。

<revision-range>

要重播的提交範圍。可以傳遞多個 <revision-range>,但在 --advance <branch> 模式下,它們應該只有一個尖端,以便清楚 <branch> 應該指向哪裡。請參閱 git-rev-parse[1] 中的「指定範圍」以及下方的「提交限制」選項。

提交限制

除了使用描述中解釋的特殊符號來指定應該列出的提交範圍之外,還可以套用額外的提交限制。

除非另有說明,否則使用更多選項通常會進一步限制輸出(例如,--since=<date1> 會限制為晚於 <date1> 的提交,並將其與 --grep=<pattern> 一起使用會進一步限制為其記錄訊息中包含符合 <pattern> 的行的提交)。

請注意,這些會在提交排序和格式化選項(例如 --reverse)之前套用。

-<number>
-n <number>
--max-count=<number>

限制輸出的提交數量。

--skip=<number>

在開始顯示提交輸出之前跳過 number 個提交。

--since=<date>
--after=<date>

顯示晚於特定日期的提交。

--since-as-filter=<date>

顯示所有晚於特定日期的提交。這會存取範圍內的所有提交,而不是停在第一個早於特定日期的提交。

--until=<date>
--before=<date>

顯示早於特定日期的提交。

--author=<pattern>
--committer=<pattern>

將輸出的提交限制為具有符合指定模式(正規表示式)的作者/提交者標頭行的提交。使用多個 --author=<pattern> 時,會選擇其作者符合任何給定模式的提交(對於多個 --committer=<pattern> 也是如此)。

--grep-reflog=<pattern>

將輸出的提交限制為具有符合指定模式(正規表示式)的 reflog 條目的提交。使用多個 --grep-reflog 時,會選擇其 reflog 訊息符合任何給定模式的提交。除非正在使用 --walk-reflogs,否則使用此選項是錯誤的。

--grep=<pattern>

將輸出的提交限制為其記錄訊息符合指定模式(正規表示式)的提交。使用多個 --grep=<pattern> 時,會選擇其訊息符合任何給定模式的提交(但請參閱 --all-match)。

--notes 生效時,會將註解中的訊息視為記錄訊息的一部分進行比對。

--all-match

將輸出的提交限制為符合所有給定的 --grep,而不是至少符合一個的提交。

--invert-grep

將輸出的提交限制為其記錄訊息不符合 --grep=<pattern> 指定的模式的提交。

-i
--regexp-ignore-case

比對正規表示式限制模式時不區分大小寫。

--basic-regexp

將限制模式視為基本正規表示式;這是預設值。

-E
--extended-regexp

將限制模式視為擴充正規表示式,而不是預設的基本正規表示式。

-F
--fixed-strings

將限制模式視為固定字串(不將模式解譯為正規表示式)。

-P
--perl-regexp

將限制模式視為 Perl 相容的正規表示式。

對這些類型的正規表示式的支援是可選的編譯時間相依性。如果 Git 在編譯時沒有支援它們,則提供此選項將會導致其終止。

--remove-empty

當給定的路徑從樹狀結構中消失時停止。

--merges

僅列印合併提交。這與 --min-parents=2 完全相同。

--no-merges

不列印具有多個父系的提交。這與 --max-parents=1 完全相同。

--min-parents=<number>
--max-parents=<number>
--no-min-parents
--no-max-parents

僅顯示具有至少(或最多)該多個父提交的提交。特別是,--max-parents=1--no-merges 相同,--min-parents=2--merges 相同。--max-parents=0 提供所有根提交,而 --min-parents=3 提供所有章魚合併。

--no-min-parents--no-max-parents 會再次重設這些限制(設為無限制)。等效形式為 --min-parents=0(任何提交都有 0 個或多個父系)和 --max-parents=-1(負數表示沒有上限)。

--first-parent

當尋找要包含的提交時,看到合併提交時僅追蹤第一個父提交。當檢視特定主題分支的演進時,此選項可以提供更好的概觀,因為合併到主題分支通常只是為了不時地調整為更新的上游,而此選項可讓您忽略因這種合併而帶入歷程記錄中的個別提交。

--exclude-first-parent-only

當尋找要排除的提交(使用 ^)時,看到合併提交時僅追蹤第一個父提交。這可用於在主題分支從遠端分支分歧的點找出主題分支中的變更集,前提是任意合併可以是有效的主題分支變更。

--not

反轉所有後續修訂規範(直到下一個 --not)的 ^ 前置字元(或缺少前置字元)的含義。當在命令列上於 --stdin 之前使用時,透過 stdin 傳遞的修訂將不受其影響。相反地,當透過標準輸入傳遞時,在命令列上傳遞的修訂將不受其影響。

--all

假裝所有在 refs/ 中的參考,連同 HEAD,都如同在命令列上列為 <commit>

--branches[=<pattern>]

假裝所有在 refs/heads 中的參考,都如同在命令列上列為 <commit>。如果給定了 <pattern>,則限制分支為符合給定 shell glob 的分支。如果模式缺少 ?*[,則預設會在結尾加上 /*

--tags[=<pattern>]

假裝所有在 refs/tags 中的參考,都如同在命令列上列為 <commit>。如果給定了 <pattern>,則限制標籤為符合給定 shell glob 的標籤。如果模式缺少 ?*[,則預設會在結尾加上 /*

--remotes[=<pattern>]

假裝所有在 refs/remotes 中的參考,都如同在命令列上列為 <commit>。如果給定了 <pattern>,則限制遠端追蹤分支為符合給定 shell glob 的分支。如果模式缺少 ?*[,則預設會在結尾加上 /*

--glob=<glob-pattern>

假裝所有符合 shell glob <glob-pattern> 的參考,都如同在命令列上列為 <commit>。如果缺少開頭的 refs/,則會自動加上。如果模式缺少 ?*[,則預設會在結尾加上 /*

--exclude=<glob-pattern>

不要包含符合 <glob-pattern> 的參考,這些參考在下一個 --all--branches--tags--remotes--glob 中會被考慮。重複使用此選項會累積排除模式,直到下一個 --all--branches--tags--remotes--glob 選項(其他選項或參數不會清除累積的模式)。

當應用於 --branches--tags--remotes 時,給定的模式不應以 refs/headsrefs/tagsrefs/remotes 開頭;當應用於 --glob--all 時,它們必須以 refs/ 開頭。如果打算加上結尾的 /*,則必須明確給定。

--exclude-hidden=[fetch|receive|uploadpack]

不要包含會被 git-fetchgit-receive-packgit-upload-pack 隱藏的參考,它們會參考適當的 fetch.hideRefsreceive.hideRefsuploadpack.hideRefs 設定,以及 transfer.hideRefs(請參閱 git-config[1])。此選項會影響下一個虛擬參考選項 --all--glob,並在處理它們之後清除。

--reflog

假裝所有 reflog 中提到的物件都如同在命令列上列為 <commit>

--alternate-refs

假裝所有在替代儲存庫中以參考提示形式提到的物件都如同在命令列上列出。替代儲存庫是指任何在其 objects/info/alternates 中指定了物件目錄的儲存庫。包含的物件集合可能會被 core.alternateRefsCommand 等修改。請參閱 git-config[1]

--single-worktree

預設情況下,當有多個工作樹時(請參閱 git-worktree[1]),以下選項會檢查所有工作樹:--all--reflog--indexed-objects。此選項會強制它們僅檢查當前的工作樹。

--ignore-missing

當在輸入中看到無效的物件名稱時,假裝沒有給定該錯誤的輸入。

--bisect

假裝不好的二分參考 refs/bisect/bad 已被列出,並且在後面跟著 --not 和好的二分參考 refs/bisect/good-* 在命令列上。

--stdin

除了從命令列取得參數外,也從標準輸入讀取參數。這接受提交和虛擬選項,例如 --all--glob=。當看到 -- 分隔符時,後續的輸入會被視為路徑,並用於限制結果。通過標準輸入讀取的標誌(例如 --not)僅對以相同方式傳遞的參數有效,並且不會影響任何後續的命令列參數。

--cherry-mark

如同 --cherry-pick(請參閱下方),但是用 = 標記等效的提交,而不是省略它們,並用 + 標記不等效的提交。

--cherry-pick

當提交集合使用對稱差異進行限制時,省略任何引入與「另一側」另一個提交相同變更的提交。

例如,如果您有兩個分支 AB,通常列出它們的單側提交的方式是使用 --left-right(請參閱下方 --left-right 選項描述中的範例)。但是,它會顯示從另一個分支 cherry-pick 的提交(例如,「b 上的第三次提交」可能從分支 A cherry-pick)。使用此選項,此類提交對會從輸出中排除。

--left-only
--right-only

僅列出對稱差異各自側的提交,也就是說,僅列出會被 --left-right 標記為 <> 的提交。

例如,--cherry-pick --right-only A...B 會從 B 中省略在 A 中或與 A 中的提交在修補程式上等效的提交。換句話說,這會列出 git cherry A B 中的 + 提交。更精確地說,--cherry-pick --right-only --no-merges 會給出確切的列表。

--cherry

--right-only --cherry-mark --no-merges 的同義詞;用於限制輸出為我們這一側的提交,並使用 git log --cherry upstream...mybranch 標記已應用於分叉歷史另一側的提交,類似於 git cherry upstream mybranch

-g
--walk-reflogs

不走訪提交的祖先鏈,而是從最新的 reflog 條目到較舊的條目走訪 reflog。當使用此選項時,您無法指定要排除的提交(也就是說,無法使用 ^commitcommit1..commit2commit1...commit2 表示法)。

使用 --pretty 格式,除了 onelinereference 之外(原因很明顯),這會導致輸出包含從 reflog 取得的額外兩行資訊。輸出中的 reflog 指定符可能會顯示為 ref@{<Nth>} (其中 <Nth> 是 reflog 中的反向時間順序索引)或 ref@{<timestamp>}(具有該條目的 <timestamp>),具體取決於一些規則

  1. 如果起始點指定為 ref@{<Nth>},則顯示索引格式。

  2. 如果起始點指定為 ref@{now},則顯示時間戳記格式。

  3. 如果沒有使用這兩者,但在命令列上給定了 --date,則以 --date 請求的格式顯示時間戳記。

  4. 否則,顯示索引格式。

--pretty=oneline 下,提交訊息會在同一行加上此資訊作為前綴。此選項不能與 --reverse 組合使用。另請參閱 git-reflog[1]

--pretty=reference 下,此資訊將完全不會顯示。

--merge

顯示在範圍 HEAD...<other> 中接觸到衝突路徑的提交,其中 <other>MERGE_HEADCHERRY_PICK_HEADREVERT_HEADREBASE_HEAD 中的第一個現有虛擬參考。僅當索引具有未合併的條目時才有效。此選項可用於在解決三向合併中的衝突時顯示相關的提交。

--boundary

輸出排除的邊界提交。邊界提交會加上 - 作為前綴。

歷史簡化

有時候您只對歷史的某些部分感興趣,例如修改特定 <path> 的提交。但 歷史簡化 有兩個部分,一部分是選擇要顯示的提交,另一部分是如何執行簡化,因為有各種簡化歷史的策略。

以下選項選擇要顯示的提交

<paths>

選擇修改給定 <paths> 的提交。

--simplify-by-decoration

選擇被某些分支或標籤引用的提交。

請注意,可能會顯示額外的提交以提供有意義的歷史。

以下選項會影響簡化的執行方式

預設模式

將歷史簡化為最簡單的歷史,以解釋樹的最終狀態。最簡單的原因是,如果最終結果相同,則會修剪一些側分支(即合併具有相同內容的分支)

--show-pulls

包含預設模式中的所有提交,以及任何與第一個父項不 TREESAME 但與後來的父項 TREESAME 的合併提交。此模式有助於顯示「首次將」變更引入分支的合併提交。

--full-history

與預設模式相同,但不修剪某些歷史。

--dense

僅顯示選定的提交,再加上一些提交以具有有意義的歷史。

--sparse

顯示簡化歷史中的所有提交。

--simplify-merges

--full-history 的額外選項,用於從結果歷史中刪除一些不需要的合併,因為沒有選定的提交對此合併做出貢獻。

--ancestry-path[=<commit>]

當給定要顯示的提交範圍時(例如 commit1..commit2commit2 ^commit1),僅顯示該範圍中是 <commit> 的祖先、<commit> 的後代或 <commit> 本身的提交。如果未指定任何提交,則使用 commit1(範圍的排除部分)作為 <commit>。可以多次傳遞;如果多次傳遞,則如果提交是給定的任何提交,或是它們其中之一的祖先或後代,則包含該提交。

下面是更詳細的解釋。

假設您指定 foo 作為 <paths>。 我們將修改 foo 的 commit 稱為 !TREESAME,其餘則為 TREESAME。(在針對 foo 過濾的 diff 中,它們分別看起來不同和相等。)

在以下內容中,我們將始終參考相同的歷史範例,以說明簡化設定之間的差異。 我們假設您正在此 commit 圖表中為檔案 foo 進行過濾

	  .-A---M---N---O---P---Q
	 /     /   /   /   /   /
	I     B   C   D   E   Y
	 \   /   /   /   /   /
	  `-------------'   X

歷史記錄 A---Q 的水平線被視為每個合併的第一個父節點。 commit 為

  • I 是初始 commit,其中 foo 的內容為「asdf」,並且檔案 quux 的內容為「quux」。 初始 commit 會與空的樹狀結構進行比較,因此 I 是 !TREESAME。

  • A 中,foo 只包含「foo」。

  • B 包含與 A 相同的變更。 其合併 M 是微不足道的,因此對所有父節點都是 TREESAME。

  • C 不會變更 foo,但其合併 N 會將其變更為「foobar」,因此對任何父節點都不是 TREESAME。

  • Dfoo 設定為「baz」。 其合併 O 將來自 ND 的字串組合成「foobarbaz」;亦即,它對任何父節點都不是 TREESAME。

  • Equux 變更為「xyzzy」,而其合併 P 將字串組合成「quux xyzzy」。 PO 是 TREESAME,但對 E 不是。

  • X 是一個獨立的根 commit,它新增了一個新檔案 side,而 Y 修改了它。 YX 是 TREESAME。 其合併 Qside 新增至 P,而 QP 是 TREESAME,但對 Y 不是。

rev-list 向後遍歷歷史記錄,根據是否使用 --full-history 和/或父節點重寫(透過 --parents--children)來包含或排除 commit。 提供下列設定。

預設模式

如果 commit 對任何父節點都不是 TREESAME,則包含該 commit(雖然這可以變更,請參閱下方的 --sparse)。 如果 commit 是合併,並且對一個父節點是 TREESAME,則只追蹤該父節點。(即使有數個 TREESAME 父節點,也只追蹤其中一個。)否則,追蹤所有父節點。

這會導致

	  .-A---N---O
	 /     /   /
	I---------D

請注意,如果有一個可用的 TREESAME 父節點,則只追蹤該父節點的規則如何完全移除了 B 的考量。 C 是透過 N 考量的,但是 TREESAME。 根 commit 會與空的樹狀結構進行比較,因此 I 是 !TREESAME。

父/子關係僅在 --parents 的情況下才可見,但這不會影響預設模式中選取的 commit,因此我們已顯示父節點行。

--full-history 沒有父節點重寫

此模式與預設模式的不同之處在於:始終追蹤合併的所有父節點,即使它對其中一個父節點是 TREESAME。 即使合併的兩側都有包含的 commit,這並不表示合併本身也包含! 在範例中,我們得到

	I  A  B  N  D  O  P  Q

M 被排除,因為它對兩個父節點都是 TREESAME。 ECB 都已遍歷,但只有 B 是 !TREESAME,因此其他 commit 不會出現。

請注意,如果沒有父節點重寫,則實際上無法談論 commit 之間的父/子關係,因此我們將它們顯示為已中斷連線。

--full-history 具有父節點重寫

只有當一般 commit 為 !TREESAME 時才會包含(雖然這可以變更,請參閱下方的 --sparse)。

合併總是會被包含。 但是,其父節點清單會被重寫:沿著每個父節點,修剪掉本身未包含的 commit。 這會導致

	  .-A---M---N---O---P---Q
	 /     /   /   /   /
	I     B   /   D   /
	 \   /   /   /   /
	  `-------------'

與上方沒有重寫的 --full-history 比較。 請注意,E 因為 TREESAME 而被修剪掉,但 P 的父節點清單被重寫為包含 E 的父節點 ICN 以及 XYQ 也發生了相同的情況。

除了上述設定之外,您還可以變更 TREESAME 是否會影響包含

--dense

如果遍歷的 commit 對任何父節點都不是 TREESAME,則包含該 commit。

--sparse

包含所有已遍歷的 commit。

請注意,如果沒有 --full-history,這仍然會簡化合併:如果其中一個父節點是 TREESAME,我們只追蹤該父節點,因此永遠不會遍歷合併的其他側。

--simplify-merges

首先,以與使用父節點重寫的 --full-history 相同的方式建立歷史圖表(請參閱上方)。

然後,根據下列規則將最終歷史記錄中的每個 commit C 簡化為其取代項 C'

  • C' 設定為 C

  • 使用其簡化項 P' 取代 C' 的每個父節點 P。 在此過程中,捨棄其他父節點的祖先或對空樹狀結構為 TREESAME 的根 commit,並移除重複項,但請注意,永遠不要捨棄所有我們為 TREESAME 的父節點。

  • 如果在此父節點重寫之後,C' 是根或合併 commit(具有零個或 >1 個父節點)、邊界 commit 或 !TREESAME,則它會保留。 否則,它會被其唯一的父節點取代。

將其與具有父節點重寫的 --full-history 比較最能顯示此效果。 範例會變成

	  .-A---M---N---O
	 /     /       /
	I     B       D
	 \   /       /
	  `---------'

請注意 NPQ--full-history 的主要差異

  • N 的父節點清單移除了 I,因為它是另一個父節點 M 的祖先。 儘管如此,N 仍保留,因為它是 !TREESAME。

  • P 的父節點清單也類似地移除了 I。 然後完全移除了 P,因為它有一個父節點且是 TREESAME。

  • Q 的父節點清單將 Y 簡化為 X。 然後移除了 X,因為它是 TREESAME 根。 然後完全移除了 Q,因為它有一個父節點且是 TREESAME。

還有另一種可用的簡化模式

--ancestry-path[=<commit>]

將顯示的 commit 限制為 <commit> 的祖先或 <commit> 的後代,或者 commit 本身。

作為一個範例使用案例,請考慮以下 commit 歷史記錄

	    D---E-------F
	   /     \       \
	  B---C---G---H---I---J
	 /                     \
	A-------K---------------L--M

常規的 D..M 會計算 M 的祖先的 commit 集,但排除 D 的祖先的 commit。 這對於了解自 D 以來導致 M 的歷史記錄發生了什麼很有用,就「M 有什麼 D 中不存在的」而言。 在此範例中的結果將是所有 commit,但 AB(當然還有 D 本身)。

但是,當我們想要找出 M 中哪些 commit 已受到 D 引入的錯誤污染且需要修正時,我們可能只想檢視實際上是 D 的後代的 D..M 子集,也就是排除 CK。 這正是 --ancestry-path 選項的作用。 應用於 D..M 範圍時,會產生

		E-------F
		 \       \
		  G---H---I---J
			       \
				L--M

我們也可以使用 --ancestry-path=D 來取代 --ancestry-path,這表示當應用於 D..M 範圍時,意義相同,但只是更明確。

如果我們對此範圍內的特定主題感興趣,以及受到該主題影響的所有 commit,我們可能只想檢視 D..M 中其祖先路徑包含該主題的子集。 因此,例如針對 --ancestry-path=H D..M 會產生

		E
		 \
		  G---H---I---J
			       \
				L--M

--ancestry-path=K D..M 會產生

		K---------------L--M

在討論另一個選項 --show-pulls 之前,我們需要建立新的歷史記錄範例。

使用者在查看簡化的歷史記錄時遇到的一個常見問題是,他們知道 commit 以某種方式變更了檔案,但該 commit 不會出現在檔案的簡化歷史記錄中。 讓我們示範一個新的範例,並展示 --full-history--simplify-merges 等選項在該案例中如何運作

	  .-A---M-----C--N---O---P
	 /     / \  \  \/   /   /
	I     B   \  R-'`-Z'   /
	 \   /     \/         /
	  \ /      /\        /
	   `---X--'  `---Y--'

對於此範例,假設 I 建立了 file.txt,該檔案由 ABX 以不同的方式修改。 單一父節點 commit CZY 不會變更 file.txt。 合併 commit M 是透過解決合併衝突來建立的,以包含來自 AB 的兩個變更,因此對兩者都不是 TREESAME。 但是,合併 commit R 是透過忽略 M 處的 file.txt 內容並僅採用 X 處的 file.txt 內容來建立的。 因此,RX 是 TREESAME,但對 M 不是。 最後,建立 N 的自然合併解決方案是採用 R 處的 file.txt 內容,因此 NR 是 TREESAME,但對 C 不是。 合併 commit OP 對其第一個父節點是 TREESAME,但對其第二個父節點 ZY 不是。

當使用預設模式時,NR 都有一個 TREESAME 父節點,因此會遍歷這些邊緣,而忽略其他邊緣。 產生的歷史圖表為

	I---X

當使用 --full-history 時,Git 會遍歷每個邊緣。 這會探索 commit AB 以及合併 M,但也會顯示合併 commit OP。 使用父節點重寫時,產生的圖表為

	  .-A---M--------N---O---P
	 /     / \  \  \/   /   /
	I     B   \  R-'`--'   /
	 \   /     \/         /
	  \ /      /\        /
	   `---X--'  `------'

在此,合併 commit OP 會產生額外的雜訊,因為它們實際上並未對 file.txt 產生變更。 它們僅合併了一個基於舊版 file.txt 的主題。 在使用工作流程的存放庫中,許多參與者同時工作並沿著單一主幹合併其主題分支時,這是一個常見的問題:許多不相關的合併會出現在 --full-history 結果中。

當使用 --simplify-merges 選項時,commit OP 會從結果中消失。 這是因為 OP 的重寫第二個父節點可以從其第一個父節點存取。 這些邊緣會被移除,然後 commit 看起來像是對其父節點為 TREESAME 的單一父節點 commit。 N 的 commit 也會發生這種情況,導致歷史記錄檢視如下

	  .-A---M--.
	 /     /    \
	I     B      R
	 \   /      /
	  \ /      /
	   `---X--'

在此檢視中,我們會看到來自 ABX 的所有重要單一父節點變更。 我們還會看到經過仔細解決的合併 M 和未經過仔細解決的合併 R。 這通常足以判斷為何 commit AB 在預設檢視中從歷史記錄中「消失」。 但是,此方法存在一些問題。

第一個問題是效能。 與任何先前的選項不同,--simplify-merges 選項需要在傳回單一結果之前遍歷整個 commit 歷史記錄。 這可能會使該選項難以用於非常大的存放庫。

第二個問題是稽核。 當許多參與者在同一個存放庫中工作時,哪個合併 commit 將變更引入重要分支是很重要的。 上方有問題的合併 R 不太可能是用於合併到重要分支中的合併 commit。 相反地,合併 N 用於將 RX 合併到重要分支中。 此 commit 可能在其 commit 訊息中包含有關為何變更 X 會覆寫來自 AB 的變更的資訊。

--show-pulls

除了預設歷史記錄中顯示的 commit 之外,還會顯示每個對其第一個父節點不是 TREESAME 但對稍後父節點為 TREESAME 的合併 commit。

--show-pulls 包含合併 commit 時,該合併會被視為從另一個分支「提取」變更。 當在此範例中使用 --show-pulls(且沒有其他選項)時,產生的圖表為

	I---X---R---N

在此,合併 commit RN 會被包含,因為它們分別將 commit XR 提取到基礎分支中。 這些合併是預設歷史記錄中沒有出現 commit AB 的原因。

--show-pulls--simplify-merges 配對時,圖表會包含所有必要的資訊

	  .-A---M--.   N
	 /     /    \ /
	I     B      R
	 \   /      /
	  \ /      /
	   `---X--'

請注意,由於 M 可以從 R 存取到,因此從 NM 的邊已被簡化移除。然而,N 仍然在歷史紀錄中作為一個重要的提交出現,因為它將變更 R 「拉」進了主分支。

--simplify-by-decoration 選項允許您只檢視歷史拓撲的整體架構,方法是省略未被標籤引用的提交。如果 (1) 提交被標籤引用,或 (2) 提交變更了命令列上給定路徑的內容,則提交會被標記為 !TREESAME (換句話說,在上述歷史簡化規則之後保留)。所有其他提交都會被標記為 TREESAME (可以被簡化移除)。

提交排序

預設情況下,提交會以反向時間順序顯示。

--date-order

在顯示任何子提交之前,不顯示任何父提交,但除此之外,按照提交時間戳記順序顯示提交。

--author-date-order

在顯示任何子提交之前,不顯示任何父提交,但除此之外,按照作者時間戳記順序顯示提交。

--topo-order

在顯示任何子提交之前,不顯示任何父提交,並避免顯示來自多個歷史線的混合提交。

例如,在像這樣的提交歷史中

    ---1----2----4----7
	\	       \
	 3----5----6----8---

其中數字表示提交時間戳記的順序,使用 --date-ordergit rev-list 和相關指令會按照時間戳記順序顯示提交:8 7 6 5 4 3 2 1。

使用 --topo-order,它們會顯示 8 6 5 3 7 4 2 1 (或 8 7 4 2 6 5 3 1);為了避免顯示來自兩個並行開發軌跡的混合提交,一些較舊的提交會顯示在較新的提交之前。

--reverse

以相反的順序輸出選擇要顯示的提交 (請參閱上面的「提交限制」章節)。不能與 --walk-reflogs 組合使用。

物件遍歷

這些選項主要針對 Git 儲存庫的打包。

--no-walk[=(sorted|unsorted)]

僅顯示給定的提交,但不遍歷其祖先。如果指定範圍,則此選項無效。如果給定參數 unsorted,則提交會按照它們在命令列上給定的順序顯示。否則 (如果給定 sorted 或沒有給定參數),則提交會按照提交時間的反向時間順序顯示。不能與 --graph 組合使用。

--do-walk

覆寫先前的 --no-walk

提交格式化

--pretty[=<format>]
--format=<format>

以給定的格式漂亮地列印提交日誌的內容,其中 <format> 可以是 onelineshortmediumfullfullerreferenceemailrawformat:<string>tformat:<string> 之一。當 <format> 不是以上任何一個,並且其中包含 %placeholder 時,它的行為就像給定了 --pretty=tformat:<format> 一樣。

請參閱「PRETTY FORMATS」章節,了解每種格式的一些其他詳細資訊。當省略 =<format> 部分時,預設為 medium

注意:您可以在儲存庫組態中指定預設的漂亮格式 (請參閱 git-config[1])。

--abbrev-commit

不顯示完整的 40 位元組十六進制提交物件名稱,而是顯示一個唯一命名該物件的前綴。可以使用「--abbrev=<n>」選項 (如果顯示,它也會修改 diff 輸出) 來指定前綴的最小長度。

這應該讓使用 80 列終端機的人更容易閱讀「--pretty=oneline」。

--no-abbrev-commit

顯示完整的 40 位元組十六進制提交物件名稱。這會否定 --abbrev-commit,無論是明確的還是由其他選項 (例如「--oneline」) 暗示的。它也會覆寫 log.abbrevCommit 變數。

--oneline

這是將「--pretty=oneline --abbrev-commit」一起使用的簡寫。

--encoding=<encoding>

提交物件會在它們的編碼標頭中記錄用於日誌訊息的字元編碼;此選項可用於告訴指令以使用者偏好的編碼重新編碼提交日誌訊息。對於非管道指令,預設為 UTF-8。請注意,如果物件聲稱是以 X 編碼,而我們正在以 X 輸出,我們將逐字輸出該物件;這表示原始提交中的無效序列可能會複製到輸出。同樣地,如果 iconv(3) 無法轉換提交,我們將安靜地逐字輸出原始物件。

--expand-tabs=<n>
--expand-tabs
--no-expand-tabs

在輸出中顯示日誌訊息之前,執行 Tab 擴展 (將每個 Tab 替換為足夠的空格,以填滿下一個顯示列,該顯示列是 <n> 的倍數)。 --expand-tabs--expand-tabs=8 的簡寫,而 --no-expand-tabs--expand-tabs=0 的簡寫,它會停用 Tab 擴展。

預設情況下,Tab 會在以 4 個空格縮排日誌訊息的漂亮格式中展開 (即 medium (預設值)、fullfuller)。

--notes[=<ref>]

在顯示提交日誌訊息時,顯示註解提交的註解 (請參閱 git-notes[1])。當命令列上沒有給定 --pretty--format--oneline 選項時,這是 git loggit showgit whatchanged 指令的預設行為。

預設情況下,顯示的註解來自 core.notesRefnotes.displayRef 變數 (或對應的環境覆寫) 中列出的註解 ref。請參閱 git-config[1],以取得更多詳細資訊。

使用可選的 <ref> 引數,使用 ref 來尋找要顯示的註解。當 ref 以 refs/notes/ 開頭時,可以指定完整的 refname;當它以 notes/ 開頭時,會加上 refs/,否則會加上 refs/notes/ 以形成 ref 的完整名稱。

可以組合多個 --notes 選項,以控制顯示哪些註解。範例:「--notes=foo」將僅顯示來自「refs/notes/foo」的註解;「--notes=foo --notes」將顯示來自「refs/notes/foo」和預設註解 ref 的註解。

--no-notes

不顯示註解。這會否定上述的 --notes 選項,方法是重設顯示註解的註解 ref 清單。選項會按照在命令列上給定的順序解析,因此例如「--notes --notes=foo --no-notes --notes=bar」將只顯示來自「refs/notes/bar」的註解。

--show-notes-by-default

顯示預設註解,除非給定顯示特定註解的選項。

--show-notes[=<ref>]
--[no-]standard-notes

這些選項已棄用。請改用上述的 --notes/--no-notes 選項。

--show-signature

透過將簽名傳遞給 gpg --verify 並顯示輸出,來檢查已簽名提交物件的有效性。

--relative-date

--date=relative 的同義詞。

--date=<format>

僅適用於以人類可讀格式顯示的日期,例如在使用 --pretty 時。log.date 組態變數會為 log 指令的 --date 選項設定預設值。預設情況下,日期會以原始時區 (提交者或作者的時區) 顯示。如果將 -local 附加到格式 (例如 iso-local),則會改用使用者的本地時區。

--date=relative 會顯示相對於目前時間的日期,例如「2 小時前」。 -local 選項對於 --date=relative 無效。

--date=local--date=default-local 的別名。

--date=iso (或 --date=iso8601) 會以類似 ISO 8601 的格式顯示時間戳記。與嚴格的 ISO 8601 格式的差異在於

  • 使用空格而不是 T 作為日期/時間分隔符號

  • 時間和時區之間有空格

  • 時區的小時和分鐘之間沒有冒號

--date=iso-strict (或 --date=iso8601-strict) 會以嚴格的 ISO 8601 格式顯示時間戳記。

--date=rfc (或 --date=rfc2822) 會以 RFC 2822 格式顯示時間戳記,通常在電子郵件訊息中找到。

--date=short 只顯示日期,而不顯示時間,格式為 YYYY-MM-DD

--date=raw 會將日期顯示為自 epoch 以來的秒數 (1970-01-01 00:00:00 UTC),後接一個空格,然後將時區顯示為與 UTC 的偏移量 (帶有四位數字的 +-;前兩位是小時,後兩位是分鐘)。也就是說,就像時間戳記以 strftime("%s %z") 格式化一樣。請注意,-local 選項不會影響自 epoch 以來的秒數值 (它始終以 UTC 測量),但會切換隨附的時區值。

--date=human 會在時區與目前時區不符時顯示時區,如果時區相符,則不會列印完整日期 (即對於「今年」的日期會跳過列印年份,但如果日期在過去幾天內,且我們可以直接說它是星期幾,則也會跳過整個日期本身)。對於較舊的日期,小時和分鐘也會省略。

--date=unix 會將日期顯示為 Unix epoch 時間戳記 (自 1970 年以來的秒數)。與 --raw 一樣,這始終以 UTC 為單位,因此 -local 無效。

--date=format:... 會將格式 ... 提供給您的系統 strftime,但 %s、%z 和 %Z 除外,這些會在內部處理。使用 --date=format:%c 以您的系統地區設定的偏好格式顯示日期。請參閱 strftime 手冊以取得完整的格式佔位符清單。使用 -local 時,正確的語法是 --date=format-local:...

--date=default 是預設格式,並且基於 ctime(3) 輸出。它會顯示單行,其中包含星期幾的三個字母、月份的三個字母、日期、時間 (格式為 "HH:MM:SS"),後接 4 位數字的年份,加上時區資訊,除非使用本地時區,例如 Thu Jan 1 00:00:00 1970 +0000

--parents

也列印提交的父提交 (格式為 "commit parent…​")。也啟用父提交重寫,請參閱上面的「歷史簡化」。

--children

也列印提交的子提交 (格式為 "commit child…​")。也啟用父提交重寫,請參閱上面的「歷史簡化」。

--left-right

標記提交是從對稱差異的哪一側可存取。來自左側的提交會加上 < 前綴,而來自右側的提交會加上 > 前綴。如果與 --boundary 組合,則這些提交會加上 - 前綴。

例如,如果您有這樣的拓撲

	     y---b---b  branch B
	    / \ /
	   /   .
	  /   / \
	 o---x---a---a  branch A

您將獲得類似這樣的輸出

	$ git rev-list --left-right --boundary --pretty=oneline A...B

	>bbbbbbb... 3rd on b
	>bbbbbbb... 2nd on b
	<aaaaaaa... 3rd on a
	<aaaaaaa... 2nd on a
	-yyyyyyy... 1st on b
	-xxxxxxx... 1st on a
--graph

在輸出的左側繪製提交歷史的文字圖形表示。為了正確繪製圖形歷史,這可能會導致在提交之間列印額外的行。不能與 --no-walk 組合使用。

這會啟用父提交重寫,請參閱上面的「歷史簡化」。

這預設會暗示 --topo-order 選項,但也可能指定 --date-order 選項。

--show-linear-break[=<barrier>]

當未使用 --graph 選項時,所有歷史分支會被展平,這可能會難以看出兩個連續的提交不屬於線性分支。在這種情況下,此選項會在它們之間設置一個分隔符。如果指定了 <barrier>,則會顯示該字串,而不是預設的字串。

輸出

當沒有衝突時,此命令的輸出可用作 git update-ref --stdin 的輸入。其格式如下:

update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH}

其中更新的參考數量取決於傳遞的參數和正在重播的歷史形狀。當使用 --advance 時,更新的參考數量始終為一個,但是對於 --onto,它可以是一個或多個(支援同時變基多個分支)。

退出狀態

對於成功的、非衝突的重播,退出狀態為 0。當重播發生衝突時,退出狀態為 1。如果由於某種錯誤而無法完成(或開始)重播,則退出狀態為 0 或 1 以外的其他值。

範例

要簡單地將 mybranch 變基到 target

$ git replay --onto target origin/main..mybranch
update refs/heads/mybranch ${NEW_mybranch_HASH} ${OLD_mybranch_HASH}

要將 mybranch 中的提交 cherry-pick 到 target 上

$ git replay --advance target origin/main..mybranch
update refs/heads/target ${NEW_target_HASH} ${OLD_target_HASH}

請注意,前兩個範例重播完全相同的提交,並且在完全相同的新基礎之上,它們的唯一區別在於,第一個範例提供了使 mybranch 指向新提交的指令,而第二個範例提供了使 target 指向新提交的指令。

如果您有一堆分支,一個分支依賴於另一個分支,並且您真的想對整個集合進行變基,該怎麼辦?

$ git replay --contained --onto origin/main origin/main..tipbranch
update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
update refs/heads/tipbranch ${NEW_tipbranch_HASH} ${OLD_tipbranch_HASH}

在呼叫 git replay 時,不需要使用 A..B 語法指定要重播的提交範圍;任何範圍表示式都可以

$ git replay --onto origin/main ^base branch1 branch2 branch3
update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH}
update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH}
update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH}

這將同時對 branch1branch2branch3 進行變基,它們自 base 以來的所有提交都將在 origin/main 之上進行重播。這三個分支可能在 base 之上有它們共有的提交,但情況不一定如此。

GIT

屬於 git[1] 套件的一部分

scroll-to-top