文章目录
  1. 1. 场景1 引入某个commit新加入的功能但不改变分支历史
  2. 2. 场景2 保持history清晰的情况下将某些提交完全移动到别的分支上
  3. 3. EXAMPLES from official guide
  4. 4. references

git-cherry-pick - Apply the changes introduced by some existing commits –from git-scm.com

我们知道在git中对分支操作的命令有mergerebasecherry-pickmerge是两条分支直接合并,rebase是追溯到共同祖先之后逐个应用当前分支的commit到所选择的基分支上,可以通过-i选项进行对当前分支的交互式变基,用以修改提交历史,git中建议以rebase方式代替普通的merge

cherry-pick在英语中是精挑细选的意思,功能也正如名字一样,是选择一些commit,将其应用到当前分支上。可以想见,其应用的主要场景是将已经提交的commit进行搬动

场景1 引入某个commit新加入的功能但不改变分支历史

直接使用cherry-pick即可,这样不会更改被引入分支的历史

1
git cherry-pick <commit hash>

默认情况下会创建一个新的提交,类似于merge。可通过选项关闭。

场景2 保持history清晰的情况下将某些提交完全移动到别的分支上

例如,我想把以下分支


A-B master
\
C-D-E-F-G topic

中的D,F commit移动到master分支,而保持其他commit不变,就像这样


A-B-D-F master
\
C-E-G topic


那么,思路是将D,F 用cherry-pick应用到master分支上,然后将topic分支对master分支变基。

1
2
3
4
5
$ git checkout master  
$ git cherry-pick D
$ git cherry-pick F
$ git checkout topic
$ git rebase master

EXAMPLES from official guide

git cherry-pick master
Apply the change introduced by the commit at the tip of the master branch and create a new commit with this change.

git cherry-pick ..master
git cherry-pick ^HEAD master
Apply the changes introduced by all commits that are ancestors of master but not of HEAD to produce new commits.

git cherry-pick maint next ^master
git cherry-pick maint master..next
Apply the changes introduced by all commits that are ancestors of maint or next, but not master or any of its ancestors. Note that the latter does not mean maint and everything between master and next; specifically, maint will not be used if it is included in master.

git cherry-pick master~4 master~2
Apply the changes introduced by the fifth and third last commits pointed to by master and create 2 new commits with these changes.

git cherry-pick -n master~1 next
Apply to the working tree and the index the changes introduced by the second last commit pointed to by master and by the last commit pointed to by next, but do not create any commit with these changes.

git cherry-pick --ff ..next
If history is linear and HEAD is an ancestor of next, update the working tree and advance the HEAD pointer to match next. Otherwise, apply the changes introduced by those commits that are in next but not HEAD to the current branch, creating a new commit for each new change.

git rev-list --reverse master -- README | git cherry-pick -n --stdin
Apply the changes introduced by all commits on the master branch that touched README to the working tree and index, so the result can be inspected and made into a single new commit if suitable.

The following sequence attempts to backport a patch, bails out because the code the patch applies to has changed too much, and then tries again, this time exercising more care about matching up context lines.

1
2
3
4
$ git cherry-pick topic^             (1)
$ git diff (2)
$ git reset --merge ORIG_HEAD (3)
$ git cherry-pick -Xpatience topic^ (4)

  • apply the change that would be shown by git show topic^. In this example, the patch does not apply cleanly, so information about the conflict is written to the index and working tree and no new commit results.

  • summarize changes to be reconciled

  • cancel the cherry-pick. In other words, return to the pre-cherry-pick state, preserving any local modifications you had in the working tree.

  • try to apply the change introduced by topic^ again, spending extra time to avoid mistakes based on incorrectly matching context lines.

references

(转)Git cherry-pick 和 rebase 的混合用法
官方文档 - git-cherry-pick

文章目录
  1. 1. 场景1 引入某个commit新加入的功能但不改变分支历史
  2. 2. 场景2 保持history清晰的情况下将某些提交完全移动到别的分支上
  3. 3. EXAMPLES from official guide
  4. 4. references