[英]How to find the common ancestor of two branches before a merge commit in git?
背景
我正在嘗試編寫一個腳本,它將使用git簡化我的backport進程。
修復當前版本中的錯誤的一般過程如下:
master
到bug修復分支,例如bugfix/abc
bugfix/abc
上的錯誤 bugfix/abc
合並到master
(沒有快進合並) 現在,當我想將修復程序向后移植到版本1時(分支v1
)我做:
bugfix/abc
創建一個新分支,例如bugfix/def
master
上的提交,例如f4d399238f
$ git rebase --onto v1 f4d399238f bugfix/def
這很好用(在解決之后我必須在合並之前使用提交進行上游)。
題
如何在合並提交之前找到兩個分支的共同祖先? (對於backport過程的第2步)。
試着
git merge-base bugfix/abc master
bugfix/abc
頭部的提交 git log
獲取此提交的子代
--reverse
,-- --ancestry-path
和--children
各種組合,但我從未達到我的預期。 更新
這個問題和Find兩個分支的共同祖先之間的關鍵區別在於兩個分支已經合並。 正如我所提到的那樣, 最好的提交將作為合並分支的負責人返回。 我需要在合並提交之前使用共同的祖先。
假設bug修復后的分支並合並到master中,如下所示:
A---B v1
\
C---D---F---H master
\ /
E---G bugfix/abc
運行$ git merge-base master bugfix/abc
將返回G但是我需要得到D (甚至F會為了使用rebase --onto
)。
一旦我得到D,我就會跑:
$ git branch bugfix/def bugfix/abc
$ git rebase --onto v1 D bugfix/def
$ git checkout v1
$ git merge bugfix/def
最終得到了預期的結果:
E'---G' bugfix/def
/ \
A---B--------I v1
\
C---D---F---H master
\ /
E---G bugfix/abc
如何在合並提交之前找到兩個分支的共同祖先? (對於backport過程的第2步)。
有幾種選擇可供使用:
git merge-base
是您要查找的命令
git merge-base在兩次提交之間找到最佳共同祖先,以便在三向合並中使用。 一個共同的祖先比另一個共同的祖先更好,如果后者是前者的祖先。 沒有任何更好的共同祖先的共同祖先是最好的共同祖先 ,即合並基礎 。 請注意,一對提交可以有多個合並基礎。
git log --decorate --graph --oneline --all
這將在日志中顯示叉點,以便您可以跟蹤分支的提交ID。
對於我所展示的情況,我找到了一個合理的解決方案:
git rev-list --first-parent master | gawk -v bugfix=bugfix/abc '{
commit = $1
branchCmd = "git branch --contains \"" commit "\" \"" bugfix "\""
if (branchCmd | getline) {
print commit
exit
}
}'
這將打印D
事實證明,如果master
被合並到bugfix/abc
,則會失敗,如下所示:
E'---G'---h' bugfix/def
/ \
A---B-------------J v1
\
C---D---F-------I master
\ \ /
E---G---H bugfix/abc
在這種情況下,它將打印F
但這仍然不是我們想要的。
如果只有branch --contains
某些選項branch --contains
來限制父母,例如--first-parent
就像有rev-list
...
解決方法是將腳本修改為以下內容:
git rev-list --first-parent master | gawk -v bugfix=bugfix/abc '{
commit = $1
branchCmd = "git branch --contains \"" commit "\" \"" bugfix "\""
if (branchCmd | getline) {
timestampCmd = "git show -s --format=%ct \"" commit "\""
if (timestampCmd | getline timestamp) {
revlistCmd = "git rev-list --first-parent --max-age=" timestamp " \"" bugfix "\""
while (revlistCmd | getline line) {
if (commit == line) {
print commit
exit
}
}
}
}
}'
這里的想法是我們采取每個可能的結果並檢查是否可以從bugfix/abc
到達,但只能跟隨第一個父進程。 --max-age
意味着我們只會在必要時返回。 如果它不可達,則它必須是從master
到bugfix/abc
的合並。 如果是,那么我們打印提交哈希並退出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.