在我们的Git流程中,“master”是当前发布周期的主题和修复分支的集成分支,但我们还维护一个“稳定”分支,我们必须谨慎地向后移植已经在master上成功测试的一些修复
所有困难都是分支已经合并回“master”(否则使用rebase非常容易 - 很多)
我描述的初始情况图:
I--J (stable)
/
/
/
- A - B - C - D - E - F - G (master)
\ /
X -- Y (fix/123)
我们想要达到的情况图表:
I--J (stable)
/ \
/ X'- Y' (fix/123-stable)
/
- A - B - C - D - E - F - G (master)
\ /
X -- Y (fix/123)
更复杂的情况是可能的,例如多次合并以完成修复:
- A - B - C - D - E - F - G - H (master)
\ / /
X - Y ----- Z (fix/123)
但是我们不允许合并到修复分支,所以我们永远不会有这样的东西:
- A - B - C - D - E - F - G (master)
\ \ /
X - Y - Z (fix/123)
为实现这一目标,我们可以挑选或修改修复分支:
1)cherry-pick(典型How do I backport a commit in git?):
git checkout -b fix/123-stable stable
git cherry-pick X Y
这似乎很容易,但在处理现实生活中的例子时并非如此;总是存在忘记一些提交或挑错的风险!
2)rebase --onto(https://www.kernel.org/pub/software/scm/git/docs/git-rebase.html):
2.a)“不工作”的方式:
git rebase --onto stable master fix/123
由于fix / 123已经合并为master,因此无效! 2.b)“不比樱桃挑选更好”的方式:
git rebase --onto stable D fix/123
这仍然存在风险,因为您需要使用D的SHA(例如,不是X)。
2.c)“使用临时起始参考”方式:
git tag begin D
git rebase --onto stable begin fix/123
git tag -d begin
这改善了以前的情况,因为标签可以更容易地进行操作或在图形工具中对其进行描绘,但仍然需要大量的手动工作。
3.d)“合并前重置硬主机”(到第一个分支点) 哼,似乎很难描述和去做。
所以,我正在寻找的是git 便携式(没有bash / grep / cut / sed暗示)的方式;
1)列出已经合并回“master”的分支上的所有提交(此处为X和Y,以及“多合并”情况下的Z)以便轻松地选择它们
2)获取已经合并回“master”
的分支的第一个分支点的提交2.a)这不能通过“git merge-base”命令完成,因为合并已经完成(甚至多次)
2.b)我在这里找到Finding a branch point with Git?以下bash命令我稍微调整了一下:
git rev-list --boundary --date-order --reverse fix/123..master | grep -m 1 - | cut -c2-
但是他不是一个简单易用的便携式命令(即没有Bash或Cygwin工具就无法工作)
答案 0 :(得分:5)
对于记录,这里是我最终使用的两个解决方案,基于answer of Craig Otis here指向answer of lindes on "Finding a branch point with Git",使用Bash别名“.gitconfig”文件(在Linux Ubuntu 12.10下测试)< / p>
初始状态,分支“fix / 123”已经合并回“master”:
I--J (stable)
/
- A - B - C - D - E - F - G (master)
\ /
X - Y (fix/123)
1)将分支“fix / 123”从“master”开始变为“稳定”(对于大多数人来说,这是一个通用答案):
将以下Bash别名添加到“.gitconfig”文件中:
[alias]
oldest-ancestor = !bash -c 'diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne \"s/^ //p\" | head -1' -
rebase-onto = !bash -c 'git rebase --onto $1 `git oldest-ancestor $2 $3` $3' -
然后使用命令行:
git rebase-onto stable master fix/123
你在这里:
I--J (stable)
/ \
/ X'- Y' (fix/123)
/
- A - B - C - D - E - F - G (master)
\ /
X - Y
2)从“master”开始重新分支“fix / 123”分支,在“stable”上创建一个新的分支“fix / 123-stable”(这是更具体的答案我我要用了。)
将以下Bash别名添加到“.gitconfig”文件中:
[alias]
oldest-ancestor = !bash -c 'diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne \"s/^ //p\" | head -1' -
rebase-onto = !bash -c 'git branch $4 $2 && git rebase --onto $3 `git oldest-ancestor $1 $4` $4' -
然后使用命令行:
git rebase-onto master fix/123 stable fix/123-stable
你在这里:
I--J (stable)
/ \
/ X'- Y' (fix/123-stable)
/
- A - B - C - D - E - F - G (master)
\ /
X - Y (fix/123)
答案 1 :(得分:4)
我对Git很新,所以请原谅我在你的情况下可能产生的任何误解。
使用此代码段:
diff -u <(git rev-list --first-parent fix/123) <(git rev-list --first-parent master) | sed -ne 's/^ //p' | head -1
从这个回答:@lindes answer to "Finding a branch point with Git?"
如果您有这样的树:
然后,some-fix
代替fix/123
的上述命令的结果将是:
f1efa4a9c029281a22d4fa8dd6607c523e7191f5
创建初始修复分支的提交。
然后,您还可以快速merge-base
运行以确定some-fix
结束的位置:
$ git merge-base master some-fix
1b9ebb7157a958e9adc3b8eda9bf4175cd821c4b
然后,使用修订范围的樱桃选择,你可以将这些变化拉出来:
$ git cherry-pick f1efa4a..1b9ebb7
你最终得到:
其中包含来自初始修复分支的其他提交。您可能需要执行额外的checkout -b
来创建fix/123-stable
分支,而不是仅将其添加到stable
,但方法应该相同。
请注意,我引用的答案提到将这个冗长乏味的diff
命令安装为名为oldest-ancestor
的别名,这样可以节省大量时间。