2014年8月27日 星期三

談 Git 的 Graft Points 及 git-replace

git merge --squash [branch] 可以將分支的修改全數合併至同一個 commit 但不會保留合併資訊,不過若是該分支持續開發,勢必會再次合併至主幹,這時如果重新使用 git merge --squash ,則已經合併過的 commit 也會因為重新被合併而造成衝突。

這時,要讓 squashed commit 同時也有 merged commit 的性質,可以利用 .git/info/grafts 這個檔案或利用 git-replace 來手動定義合併資訊製作造假的合併資訊!

好用的地方在哪個? 假設你有兩個 perforce branch,分支之間不斷大量修改合併,但使用 git-p4 clone 後,你希望這兩個 branch 的合併基底 (merge base) 重新計算,減少合併衝突,就可以利用這個 graft point 來定義合併節點。

甚至是 git-svn 在處理樹狀目錄的合併資訊,也可以利用 graft points 來定義合併節點減少合併衝突。

當儲存倉越來越大時,你也可以將某個 commit 之前的 history 全數壓縮到另外一個儲存倉並把古老的 commit history 全數壓起來 (squash) 來節省空間...要查看細節時,再用 git-replace 將 commit history 接回來即可。

但 .git/info/grafts 只存在 local 端,並不會被 push 出去,因此若要能修改整個 commit tree 可利用 git replace --graft […] 直接將 commit 換掉 parent。

參見:

git-replace: http://git-scm.com/docs/git-replace.html

Graft Point: https://git.wiki.kernel.org/index.php/GraftPoint

#ThePowerfulGit