如何挑选单个提交、多个提交或一系列提交
...到您当前签出的分支:
1. 挑选一个名为的_分支_或提交commit
例子:
git cherry-pick my_branch # by branch name
git cherry-pick 1e038f108a130831f108329b1083a8139813fabc # by full hash
git cherry-pick 1e038f10 # by partial hash
2. 挑选_多个_提交
请注意,您可以按您想要的任何顺序一次挑选_任意数量的提交哈希值__。_它们只会按照您指定的顺序一次应用一个。如果出现任何冲突,您必须一次解决一个问题,然后在完成后使用git add my_file
thengit cherry-pick --continue
继续挑选过程。
git cherry-pick commit1 commit2 commit3 commit4 commit5
3. 挑选_一系列_提交
我最初是从@Eric Darchis 在这里获得最多支持的答案中学习了这种风格的基础知识。
请注意,要挑选一系列_提交_,您必须指定开始和结束提交哈希,以及..
它们之间的值。但是,在一系列提交中,不包括开始提交。因此,要包含它,您必须在开始提交_之前_指定提交。_指定前面_提交的语法是在提交_之后_放置~
、~1
或 ,如: ,这意味着^
:“之前的提交”。beginning_commit~``beginning_commit
# A. INCLUDING the beginning_commit
git cherry-pick beginning_commit~..ending_commit
# OR (same as above)
git cherry-pick beginning_commit~1..ending_commit
# OR (same as above)
git cherry-pick beginning_commit^..ending_commit
# B. NOT including the beginning_commit
git cherry-pick beginning_commit..ending_commit
注意: commit~
、commit~1
和all 表示“之前的commit^
一次提交”,或者换句话说:“之前的提交”。 commit``commit
要指定之前的_两次_commit
提交,您可以使用如下语法:
commit~~
commit~2 # my preferred syntax
commit^^
要指定之前的_三个_commit
提交,您可以执行以下操作:
commit~~~
commit~3 # my preferred syntax
commit^^^
这不起作用:
commit^3 # INVALID syntax
这_确实_有效,但这是一个非常特殊的情况。另请参阅我的问答:在git merge
-style 工作流程中,仅显示合并之前某人在其 PR(拉取请求)功能分支中拥有的唯一提交:
# valid on **merge commits** only
commit^2 # this is the immediate **right** parent of the two parents
# involved in the merge (which made commit `commit`)
# valid on any commits (gets the left parent of a merge commit, or
# the only parent of a non-merge commit)
commit~ # and this is the immediate **left** parent of the two
# parents involved in the merge (which made commit `commit`)
要自己测试上述“先前提交语法”概念,最简单的方法是使用git log
命令。前任:
git log commit
git log commit~
git log commit~1
git log commit^
git log commit~~
git log commit~5
# etc.
4. 挑选一系列同行的提交到您的分支上
...当他们的分支peer_branch
从您的分支的早期版本中分叉出来时my_branch
。
快速总结
# you cherry-pick all of their extra commits from their `peer_branch` onto
# your `my_branch` (note: the 3 dots below are very important!)
git fetch origin peer_branch # get their latest changes from the remote
git checkout my_branch # ensure you're on your branch
# cherry-pick their range of commits
git cherry-pick my_branch...origin/peer_branch
git log # review the commits you just chery-picked
git push # push your changes to the remote
提交范围内 2 点和 3 点之间的差异非常显着。git diff branch1...branch2
相当于git diff $(git merge-base branch1 branch2) branch2
. branch2
当您想要查看自 偏离 以来所做的更改branch1
,而不是两个分支在当前状态下的差异时,这非常有用。请参阅此处和此处的评论以及此处的答案:What are the Differences between double-dot ".." and Triple-dot "..." in Git diff commit Ranges?
完整的详细信息和工作流程演练
假设您正在开发功能分支my_branch
,而您的同事希望帮助您进行一些更改以帮助您完成功能。您已经推my_branch
送到名为 的远程origin
。因此,他们将获取名为my_branch
其本地计算机的远程分支,从中分叉出自己的名为 的分支peer_brach
,然后推送到自己名为 的分支peer_branch
。一旦他们这样做了,你就可以立即挑选他们添加的所有内容。该过程的第一部分如下所示:
# **your peer** does this
# peer fetches your branch named `my_branch` and forks their `peer_branch`
# off of it
# they fetch your latest work from remote `my_branch` into their locally-stored
# remote-tracking "hidden" branch named `origin/my_branch`
# (note: you can see all locally-stored remote-tracking "hidden" branches
# with `git branch -r`)
git fetch origin my_branch
# create `peer_branch` as a fork off of `origin/my_branch`, and check it out
git checkout -b peer_branch origin/my_branch
# Now they can add their changes and commits and `git push` to remote `origin`
# as their own `peer_branch` when done.
现在他们已经将所有更改推送到远程origin
作为他们自己的名为 的分支peer_branch
,您可以挑选他们添加到您的工作之上的_所有提交,如下所示:_
# **you** do this to cherry-pick your peer's helpful changes they added to
# your work
# you fetch their latest work from their branch named `peer_branch` on remote
# `origin` into your locally-stored remote-tracking "hidden" branch named
# `origin/peer_branch`
# (note: you can see all locally-stored remote-tracking "hidden" branches
# with `git branch -r`)
git fetch origin peer_branch
# ensure you are on `my_branch` (if you aren't already)
git checkout my_branch
# you cherry-pick all of their extra commits from their `peer_branch` onto
# your `my_branch` (note: the 3 dots here are very important!)
git cherry-pick my_branch...origin/peer_branch
git log # review the commits you just chery-picked
git push # push your changes to the remote
为了您的理解,cherry-pick
上面那个带有 3 个点的命令_完全等同_于这个更长的命令:
git cherry-pick $(git merge-base my_branch origin/peer_branch)..origin/peer_branch
该部分查找branch和branchgit merge-base my_branch origin/peer_branch
之间的公共父提交哈希。这是他们从你的你的. 然后,您当然会挑选从该点到 ( ) 的最终提交_的提交范围_。my_branch``origin/peer_branch``peer_branch``my_branch``..``origin/peer_branch
要了解有关 3 点语法的更多信息,请参阅此处:Git diff 提交范围中双点“..”和三点“...”之间的区别是什么?[复制]。有关 的帮助git checkout -b new_branch from_branch
,请参阅我的答案:从另一个分支在 git 中创建分支的各种方法
官方 Git 文档
- https://git-scm.com/docs/gitrevisions - 提到 git commit 3 点 (
...
) 与 2 点范围语法、^commit
("not" commit
)、commit^
( 的父级commit
) 等。
更进一步
- 还有一点需要知道: a
git rebase
只是一堆连续的git cherry-pick
s。请参阅我的其他答案(根据 Git,谁是“我们”,谁是“他们”?),其中我展示了我制作的 ASCII 绘图,其中显示了 a 的git rebase
工作原理及其正在执行的操作。
- Git diff 提交范围中的双点“..”和三点“...”有什么区别?[复制]
- 我对从另一个分支在 git 中创建分支的各种方法的回答
- 我的问答:在
git merge
风格的工作流程中,仅显示合并之前某人在其 PR(拉取请求)功能分支中的唯一提交