假設我有我的地方,唯一分支機構以下版本歷史:如何在過去的兩個任意版本之間注入一個版本?
A -- B -- C
如何插入A和B之間的新版本X,所以該版本歷史是這樣的:
A -- X -- B -- C
請注意,在how to insert a commit in the past上有類似的問題,但在我的情況中,它有點不同:由X引入的任何更改都不會傳播給B,在A和B之間插入版本X後,它應該保持不變。
假設我有我的地方,唯一分支機構以下版本歷史:如何在過去的兩個任意版本之間注入一個版本?
A -- B -- C
如何插入A和B之間的新版本X,所以該版本歷史是這樣的:
A -- X -- B -- C
請注意,在how to insert a commit in the past上有類似的問題,但在我的情況中,它有點不同:由X引入的任何更改都不會傳播給B,在A和B之間插入版本X後,它應該保持不變。
I如果你想添加提交,但是使它對源代碼沒有任何影響,那麼是的,你確實需要一個不同於交互式底圖的路徑。
沒有什麼專門爲此設計的,但它是相對容易git replace
做到:
A
(作爲一個分離的頭,或在一個新的分支,但新的分支將很快無用):git checkout <hash-of-A>
。X
(但你希望它出現)。git replace --graft <hash-of-B> HEAD
。你現在有這個實際歷史:
X--B' <-- refs/replace/<hash-of-B>
/
A--B--C <-- whatever-branch-this-is
什麼特別的這些「替代」的對象是,每當Git是關於與做幾乎任何事情幾乎任何對象,包括「使用提交的任何目的「,例如,Git會查看是否存在帶對象哈希ID的refs/replace/
名稱。由於是替代B
,所以Git現在將替代爲B'
。因此,git log
和其他Git命令將充當雖然歷史是:
A--X--B'--C
注意,但是,真正的歷史是仍然存在於這個倉庫。當且僅當refs/replace/
名稱在存儲庫中 - 當然這是這個存儲庫 - 和替換被啓用(其是默認情況下),使用替代歷史。但是,如果您在別處克隆或推送此存儲庫,則取或推過程通常不會傳輸任何名稱;因此該存儲庫的克隆將切換回舊的歷史記錄。 (您也可以通過禁用替換來查看原始歷史記錄,例如使用git --no-replace-objects log ...
)。
如果您願意,現在可以運行git filter-branch
,它僅僅複製提交。默認情況下,git filter-branch
服從替換規則。這意味着當它複製分支上的提交時,它將以A
開頭,然後複製X
,然後複製B'
,然後複製C
指向B'
。 A
,X
和B'
的副本將與原件完全相同,因此實際上會重新使用原件;但C
的副本會略有不同:它將使用B'
作爲其真正的家長,而不是作爲替代嫁接的家長。所以提交C
將被複制到新的提交C'
,並且分支名稱(無論它是什麼)將被指向新副本。
此過濾分支有實際(不只是移植)的歷史,穿越回過B'
到X
到A
,所以現在如果你克隆過濾庫,在克隆看到的歷史將同樣從C'
開始,然後其通過B'
至X
至A
。