方法git backport(rebase / cherry-pick)已经合并的分支 [英] How-to git backport (rebase/cherry-pick) an already merged branch

查看:299
本文介绍了方法git backport(rebase / cherry-pick)已经合并的分支的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我们的Git过程中,master是当前发布周期的主题和修复分支的集成分支,但我们也维护一个稳定分支,我们必须仔细地回溯我们已经在master上成功测试的一些修复。



所有的困难是该分支已经被合并回master中(否则它很容易与rebase - )




  • 我们不想改变这个过程,因为a)我们不想修改stable 分支和b)我们有时必须对稳定分支进行一些更改,我们不希望在主中进行合并。

  • 显然,我们无法合并修补程序进入稳定分支,因为这将支持许多不需要的功能。



我描述的初始状态图:

  I  -  J(稳定)
/
/
/
- A - B - C - D - E - F - G(mas ter)
\ /
X - Y(fix / 123)

我们想要达到的情况图:

  I  -  J(稳定)
/ \
/ X'- Y'(fix / 123-stable)
/
- A - B - C - D - E - F - G(主)
\\ / /
X - Y(fix / 123)

更复杂的情况是可能的,例如($)
$ b

   -  A  -  B  -  C  -  D  -  E  -  F  -  G  -  H(主) 
$ /
X - Y ----- Z(fix / 123)

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

  -  A  -  B  -  C  -  D  -  E  -  F  -  G(主)
\\
X - Y - Z(fix / 123)

实现此目的,我们可以选择或重新绑定修复分支:

<1> cherry-pick(typicaly 我该如何在git中提交一个提交?):

  git checkout -b fix / 123-stable stable 
git cherry-pick XY

这看起来很容易,但是在处理现实生活中的例子时不是这样。忘记一些提交或挑错的风险总是有风险的!

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



2.a)不工作的方式:

pre > git rebase --onto stable master fix / 123

修复/ 123已经合并为主!
2.b)比樱桃挑选方式要好:

  git rebase --onto stable D fix / 123 

这仍然是一种风险,因为您需要采用D的SHA(和例如NOT 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)轻松挑选它们
$ b $ 2获得已经合并回master的分支的第一个分支点的提交

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


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

  git rev-list --boundary --date-order  - 反向修复/ 123..master | grep -m 1  -  | cut -c2- 

但他不是git easy也不是便携式命令(即没有Bash或Cygwin工具)

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



初始状态分支fix / 123已经被合并回master中

  I  -  J (稳定的)
/
- A - B - C - D - E - F - G(主)
\\ /
X - Y(fix / 123)






1) 123从主开始到稳定(这是一个对于大多数读者来说,通用答案



将以下Bash别名添加到您的.gitconfig文件中:

  [别名] 
最老的祖先=!bash -c'diff -u<(git rev-list --first-parent $ {1:-master})<(git rev-list --first-parent$ {2:-HEAD})| sed -ne \s / ^ // p \|头-1' -
rebase-on =!bash -c'git rebase --onto $ 1`git old-ancestor $ 2 $ 3` $ 3' -

然后使用命令行:

  git rebase-to stable master fix / 123 

您在这里:

< (定价/ 123)
/
- I - J(稳定)
/ \
/ A - B - C - D - E - F - G(主)
\\ /
X - Y






2)从master开始重新分支fix / 123,创建一个新分支fix / 123-stable 到stable(这是我将要使用的更具体的答案)。



将以下Bash别名添加到.gitconfig文件中:

  [别名] 
最古老的祖先=!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-to =!bash -c'git branch $ 4 $ 2&& git rebase --onto $ 3`git old-ancestor $ 1 $ 4` $ 4' -

然后使用命令行:

  git rebase-to master fix / 123稳定修正/ 123稳定


$ b

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


In our Git process, "master" is the integration branch for topic and fix branches for the current release cycle, but we also maintain a "stable" branch where we have to backport carefully some of our fixes already successfully tested on master.

All the difficulty is that the branch has already been merged back in "master" (else it is really easy with rebase --onto)

  • We don't want to change the process the other way because a) we don't want to fix everything in the "stable" branch, and b) we sometimes have to make some changes to the "stable" branch that we don't want to merge in "master".
  • Clearly, we cannot merge the fix into the "stable" branch because this will backports many unwanted features.

Graph of the initial situation I describe :

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

Graph of the kind of situation we want to reach :

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

More complex cases are possible, such as multiple merge to complete a fix :

- A - B - C - D - E - F - G - H (master) 
               \     /       /
                X - Y ----- Z (fix/123)

But we don't allow merge into a fix branch, so we shall never have something like this :

- A - B - C - D - E - F - G (master) 
               \   \     /
                X - Y - Z (fix/123)

To achieve this, we can cherry-pick or rebase the fix branch :

1) cherry-pick (typicaly How do I backport a commit in git?) :

git checkout -b fix/123-stable stable
git cherry-pick X Y

This seems easy, but it is not when dealing with real life examples ; there is always a risk to forget some commits, or to pick wrong ones!

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

2.a) the "not working" way :

git rebase --onto stable master fix/123

This does nothing since fix/123 has already been merged to master! 2.b) the "not far better than cherry-pick" way :

git rebase --onto stable D fix/123

This is still kind of risky because you need to take the SHA of D (and NOT X for instance).

2.c) the "use a temporary starting ref" way :

git tag begin D
git rebase --onto stable begin fix/123
git tag -d begin

This improve the previous situation, as the tag make it easier to do it or picture it in a graphical tool, but it is still lot of manual work.

3.d) the "reset hard master before the merge" (to the first branching point) Hum, seems hard to describe and to do.

So, what I am looking for is a git portable (no bash/grep/cut/sed implied) way to either;

1) list all commits made on a branch already merged back into "master" (here X and Y, and also Z in the "multi-merged" case) to cherry-pick them easily

2) get the commit of the first branch point of a branch already merged back into "master"

2.a) this cannot be done by the "git merge-base" command because the merge is already done (even multiple time)

2.b) I've found here Finding a branch point with Git? the following bash command I tweaked a bit:

git rev-list --boundary --date-order --reverse fix/123..master | grep -m 1 - | cut -c2-

but his is not a git easy nor portable command (ie not working without Bash or Cygwin tools)

解决方案

For the record, here are the two solutions I am finally using based on the answer of Craig Otis here pointing at the answer of lindes on "Finding a branch point with Git", using Bash aliases the ".gitconfig" file (tested under Linux Ubuntu 12.10)

Initial state, where the branch "fix/123" has already been merged back into "master":

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


1) To rebase the branch "fix/123" starting from "master" onto "stable" (this is a generic answer for most people reading this):

Add the following Bash aliases into your ".gitconfig" file:

[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' -

Then use the command line:

git rebase-onto stable master fix/123

And here you are:

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


2) To rebase the branch "fix/123" starting from "master", creating a new branch "fix/123-stable" onto "stable" (this is the more specific answer I am going to use).

Add the following Bash aliases into your ".gitconfig" file:

[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' -

Then use the command line:

git rebase-onto master fix/123 stable fix/123-stable

And here you are:

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

这篇关于方法git backport(rebase / cherry-pick)已经合并的分支的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆