【git】彻底搞清楚 cherry-pick -m

用于将一个存在的commit提交到一个分支。用处在于:

(1)如多数人所说,有两个分支,一个是稳定版,一个是开发版,如果想把后续几个开发版的commit上线,可以使用cherry-pick把相应的commit追加到稳定版;

(2)有时,测试环境和开发环境的版本不同,我们一般从master clone一个最新版本到自己的开发分支比如dev,再基于dev开发。开发完以后,需要把自己的改动放到测试分支比如staging进行测试。一般情况下,测试环境staging分支可能会与master区别较大,导致staging与dev也差别较大,如果直接在staging上merge我们的dev,需要解决N多冲突,十分麻烦。所以更好的做法是,先切到staging分支,再把我们dev上新开发的提交cherry-pick到staging分支,这样就不需要处理冲突了,更加方便。

 

cherry-pick的原理是使用补丁,也就是说cherry-pick A,就相当于把从A^到A的变化应用于当前分支。那么如果A是一个merge的commit,问题就来了,这个A^怎么确定?因为A有两个父节点。这时,直接cherry-pick会报错,解决办法就是使用-m参数。

-m后面跟一个从1开始的数字,表示的就是要用哪一个父节点生成补丁,也就是决定A^。数字的顺序与merge节点的顺序一致,我们可以使用git log查看merge节点,merge节点的提交信息会包含多个父节点,然后用“,”隔开,这个顺序就是-m的顺序。至此,-m也就清楚了。下面举例:

现在是master分支,然后master分出了一个staging分支,基于staging新建一个提交s,同时切到master也新建一个提交m,这时s和m已经分叉。在master分支上merge staging:

git co master;

git merge staging;

git log;

此时,会有产生一个merge节点假设为A。并且git log里,A信息大致为:Merge:m s。意味着m是A的第一父节点。

 

在另一个分支上cherr-pick这个A,

如果运行:git cherry-pick A -m 1,表明A的父节点指定为第一个父节点,也就是m,此时生成的补丁内容是从m如何到A,其实也就是s提交的内容(A包含了s和m)。所以实际上cherry-pick的是s提交;

同理,如果运行:git cherry-pick A -m 2,表明A的父节点指定为第二个父节点,也就是s,此时生成的补丁内容是从s如何到A,其实也就是m提交的内容。所以实际上cherry-pick的是m提交;

 

这个问题搞了我一下午-_-||

最后附上大神的回答:https://stackoverflow.com/questions/12626754/git-cherry-pick-syntax-and-merge-branches/12628579#12628579

You have to supply -m if the commit is a merge commit, i.e. a commit with more than one parent.

Normally, what git cherry-pick REV does can be described as:

  1. Take the changes between rev and its parent.

  2. Apply these changes to the current HEAD and commit the result with rev's commit message.

A merge commit joins two lines of development. For example, one line implements widget, and the other line removes clutter. The merge gives you the code with the widget, sans the clutter.

Now consider step #1 of the cherry-pick process: git can't guess whether you want to remove the clutter or to implement the widget. Nor can you do both, because the information on how to do both is not contained inside a single merge commit, only the content of the resultant merged tree is.

The -m option allows you to tell git how to proceed. For example, if clutter removal happened on master and the merge commit was created using git merge WIDGET, then git cherry-pick -m 1 merged-commit will cherry-pick the new widget because diff between the merged tree and parent 1 (the last of clutter-removing commits) will have been exactly the widget addition. On the other hand, git cherry-pick -m 2 merge-commit will delete the clutter, because the difference between parent 2 (the last of the widget-adding commits) and merge-commit is exactly the clutter-removal missing from the widget branch.

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值