如何git backport(rebase/cherry-pick)已经合并的分支

SRo*_*uts 4 git branch rebase cherry-pick

在我们的Git流程中,"master"是当前发布周期的主题和修复分支的集成分支,但我们还维护一个"稳定"分支,我们必须谨慎地向后移植已经在master上成功测试的一些修复.

所有困难都是分支已经合并回"master"(否则它很容易与rebase --onto)

  • 我们不希望以另一种方式改变过程,因为a)我们不想修复"稳定"分支中的所有内容,以及b)我们有时必须对"稳定"分支进行一些修改我想合并"主".
  • 显然,我们无法将修复程序合并到"稳定"分支中,因为这会向后移植许多不需要的功能.

我描述的初始情况图:

          I--J (stable)
         /
        /
       /
- A - B - C - D - E - F - G  (master) 
              \      /
               X -- Y (fix/123)
Run Code Online (Sandbox Code Playgroud)

我们想要达到的那种情况的图表:

          I--J (stable)
         /    \
        /      X'- Y' (fix/123-stable)
       /
- A - B - C - D - E - F - G  (master) 
              \      /
               X -- Y (fix/123)
Run Code Online (Sandbox Code Playgroud)

更复杂的情况是可能的,例如多次合并以完成修复:

- A - B - C - D - E - F - G - H (master) 
               \     /       /
                X - Y ----- Z (fix/123)
Run Code Online (Sandbox Code Playgroud)

但我们不允许合并到一个修复分支,所以我们永远不会有这样的东西:

- A - B - C - D - E - F - G (master) 
               \   \     /
                X - Y - Z (fix/123)
Run Code Online (Sandbox Code Playgroud)

为实现这一目标,我们可以挑选或修改修复分支:

1)cherry-pick(典型地如何在git中向后端移植提交?):

git checkout -b fix/123-stable stable
git cherry-pick X Y
Run Code Online (Sandbox Code Playgroud)

这似乎很容易,但在处理现实生活中的例子时并非如此; 总是存在忘记一些提交或挑错的风险!

2)rebase --onto(https://www.kernel.org/pub/software/scm/git/docs/git-rebase.html):

2.a)"不工作"的方式:

git rebase --onto stable master fix/123
Run Code Online (Sandbox Code Playgroud)

这没有任何作用,因为fix/123已经合并为master!2.b)"不比樱桃挑选更好"的方式:

git rebase --onto stable D fix/123
Run Code Online (Sandbox Code Playgroud)

这仍然有点冒险,因为您需要使用D的SHA(例如,不是X).

2.c)"使用临时起始参考"的方式:

git tag begin D
git rebase --onto stable begin fix/123
git tag -d begin
Run Code Online (Sandbox Code Playgroud)

这改善了以前的情况,因为标签使其更容易实现或在图形工具中进行描绘,但仍然需要大量的手动工作.

3.d)"合并前重置硬主人"(到第一个分支点)哼,似乎很难描述和去做.

所以,我正在寻找的是一个git 便携式(没有bash/grep/cut/sed隐含)的方式;

1)列出已经合并回"master"的分支上的所有提交(这里是X和Y,以及"多合并"情况下的Z),以便轻松地挑选它们

2)获取已经合并回"master"的分支的第一个分支点的提交

2.a)这不能通过"git merge-base"命令完成,因为合并已经完成(甚至多次)

2.b)我在这里找到了用Git寻找分支点?我调整了以下bash命令:

git rev-list --boundary --date-order --reverse fix/123..master | grep -m 1 - | cut -c2-
Run Code Online (Sandbox Code Playgroud)

但他不是一个简单易用的便携式命令(即没有Bash或Cygwin工具就无法工作)

SRo*_*uts 5

为了记录,这里是我最终使用的两个解决方案,基于Craig Otis回答,在这里指出lindes在"使用Git查找分支点"答案,使用Bash别名".gitconfig"文件(在Linux下测试) Ubuntu 12.10)

初始状态,分支"fix/123"已经合并回"master":

        I--J (stable)
       /
- A - B - C - D - E - F - G  (master) 
               \     /
                X - Y (fix/123)
Run Code Online (Sandbox Code Playgroud)

1)将从"master"开始的分支"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 rebase --onto $1 `git oldest-ancestor $2 $3` $3' -
Run Code Online (Sandbox Code Playgroud)

然后使用命令行:

git rebase-onto stable master fix/123
Run Code Online (Sandbox Code Playgroud)

你在这里:

          I--J (stable)
         /    \
        /      X'- Y' (fix/123)
       /
- A - B - C - D - E - F - G  (master) 
               \     /
                X - Y
Run Code Online (Sandbox Code Playgroud)

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' -
Run Code Online (Sandbox Code Playgroud)

然后使用命令行:

git rebase-onto master fix/123 stable fix/123-stable
Run Code Online (Sandbox Code Playgroud)

你在这里:

          I--J (stable)
         /    \
        /      X'- Y' (fix/123-stable)
       /
- A - B - C - D - E - F - G  (master) 
               \     /
                X - Y (fix/123)
Run Code Online (Sandbox Code Playgroud)

  • 既然你的回答是基于克雷格的工作,我认为他也应该得到一个赞成. (2认同)