背景
我正在尝试编写一个脚本,它将使用git简化我的backport进程。
修复当前版本中的错误的一般过程如下:
master
分支到错误修复分支,例如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
结合#1的结果来获取此提交的子级
--reverse
,--ancestry-path
和--children
的各种组合关注How do I find the next commit in git?,但我从未得到我的预期。更新
这个问题与Find common ancestor of two branches之间的主要区别在于两个分支已经合并。正如我所提到的,最佳提交作为合并分支的头部返回。我需要在合并提交之前使用共同的祖先 。
假设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
答案 0 :(得分:3)
如何在合并提交之前找到两个分支的共同祖先? (对于backport过程的第2步)。
有几种选择:
git merge-base
是您要查找的命令
git merge-base 在两次提交之间找到最佳共同祖先,以便在三向合并中使用。如果后者是前者的祖先,一个共同的祖先更好比另一个共同的祖先。没有任何更好的共同祖先的共同祖先是最佳共同祖先,即合并基础。请注意,一对提交可以有多个合并基础。
git log --decorate --graph --oneline --all
这将在日志中显示叉点,以便您可以跟踪分支的提交ID。
答案 1 :(得分:0)
对于我所展示的情况,我找到了一个合理的解决方案:
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
只有一些选项限制父母,例如--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
的合并。如果是,那么我们打印提交哈希并退出。