如何挑选多个提交
我有两个分支机构。 Commit a
是其中一个的头部,而另一个则有 b
、c
、d
、e
和 f
位于 a
之上。我想将 c
、d
、e
和 f
移动到第一个分支而不提交 b.使用cherry pick很简单:签出第一个分支cherry-pick一个一个地从
c
到f
并将第二个分支重新设置为第一个分支。但是有没有办法在一个命令中挑选所有 c
-f
呢?
以下是该场景的直观描述(感谢 JJD):
I have two branches. Commit a
is the head of one, while the other has b
, c
, d
, e
and f
on top of a
. I want to move c
, d
, e
and f
to first branch without commit b
. Using cherry pick it is easy: checkout first branch cherry-pick one by one c
to f
and rebase second branch onto first. But is there any way to cherry-pick all c
-f
in one command?
Here is a visual description of the scenario (thanks JJD):
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
Git 1.7.2 引入了挑选一系列提交的功能。来自发行说明:
要挑选从提交
A
到提交B
的所有提交(其中A
早于B
), run:如果您想忽略 A 本身,请运行:
注释中的注释:
A
应该早于B
或A< /code> 应该来自另一个分支。
A^^..B
因为插入符号需要转义,或者应该是"A^..B"
(双引号)。zsh
shell 中,它应该是'A^..B'
(单引号),因为插入符号是特殊字符。(感谢评论中的 damian、JB Rainsberger、sschaef、Neptilo、Pete 和 TMin。)
Git 1.7.2 introduced the ability to cherry pick a range of commits. From the release notes:
To cherry-pick all the commits from commit
A
to commitB
(whereA
is older thanB
), run:If you want to ignore A itself, run:
Notes from comments:
A
should be older thanB
, orA
should be from another branch.A^^..B
as the caret needs to be escaped, or it should be"A^..B"
(double quotes).zsh
shell, it should be'A^..B'
(single quotes) as the caret is a special character.(Credits to damian, J. B. Rainsberger, sschaef, Neptilo, Pete and TMin in the comments.)
如果您有选择性的修订要合并,例如来自 A、B、C、D、E、F、G、H、I、J 提交的 A、C、F、J,只需使用以下命令:
If you have selective revisions to merge, say A, C, F, J from A,B,C,D,E,F,G,H,I,J commits, simply use the below command:
如何挑选单个提交、多个提交或一系列提交
...到当前签出的分支:
1. 挑选单个 名为
commit
的分支或提交示例:
2. 挑选多个提交
请注意,您可以挑选任意数量的提交哈希一次,并且按照您想要的任何顺序。它们只会按照您指定的顺序一次应用一个。如果出现任何冲突,您必须一次解决一个问题,然后使用 git add my_file ,然后在完成后使用 gitcherry-pick --Continue 继续樱桃采摘过程。
3. 挑选范围的提交
我最初是从最受好评的文章中学习这种风格的基础知识的@Eric Darchis 在这里回答。
请注意,要挑选范围的提交,您必须指定开始和结束提交哈希,并在它们之间使用
..
。但是,在一系列提交中,不包括开始提交。因此,要包含它,您必须在开始提交之前指定提交。指定前面提交的语法是将~
、~1
或^
放在之后 你的提交,如:beginning_commit~
,这意味着:“在beginning_commit
之前的提交”。注意:
commit~
、commit~1
和commit^
均表示“在commit
”,或者说:“commit
之前的提交”。要在
提交
之前指定两次次提交,您可以使用如下语法:要在
提交
之前指定三次次提交,你可以这样做:这不起作用:
这确实有效,但这是一个非常特殊的情况。另请参阅我的问答:在
git merge
风格的工作流程中,仅显示某人在合并之前的 PR(拉取请求)功能分支:要自己测试上述“先前提交语法”概念,最简单的方法是使用 git log 命令。例如:
要挑选一系列同级的提交到您的分支上
4.当您的同级分支
peer_branch
是从您的分支my_branch
的早期版本分叉出来时,。快速总结
提交范围内的 2 点和 3 点之间的差异非常显着。
git diffbranch1...branch2
相当于git diff $(git merge-basebranch1branch2)branch2
。当您想要查看在branch2
中所做的更改(因为它与branch1
不同)而不是两个分支在当前状态下的差异时,这非常有用。请参阅我的在这里评论和这里以及这里的答案: Git diff 提交范围中的双点“..”和三点“...”有什么区别?完整详细信息和工作流程演练
假设您正在开发功能分支
my_branch
,并且您的同事希望帮助您进行一些更改,以帮助您完成功能。您已经将my_branch
推送到名为origin
的远程。因此,他们会将名为my_branch
的远程分支获取到本地计算机,从中分叉出自己名为peer_brach
的分支,然后推送到自己名为的分支>peer_branch
。一旦他们这样做了,你就可以立即挑选他们添加的所有内容。这个过程的第一部分是这样的:现在他们已经将所有更改推送到远程
origin
作为他们自己的名为peer_branch
的分支,您可以挑选他们在您的工作之上添加的所有提交如下所示:为了您的理解,上面的
cherry-pick
命令(其中有 3 个点)是 与这个较长的命令完全相同:git merge-base my_branch origin/peer_branch
部分查找分支my_branch
和分支origin 之间的公共父提交哈希/peer_branch
。这是他们从您的my_branch
分叉出自己的peer_branch
的提交。然后,您当然会挑选从该点到 (..
) 在origin/peer_branch
的最终提交的提交范围 >。要了解有关三点语法的更多信息,请参阅此处:双点“..”和三点“之间有什么区别...”在 Git diff 提交范围中? [重复]。有关 git checkout -b new_branch from_branch 的帮助,请参阅我的答案:在 git 中创建分支的各种方法来自另一个分支
官方 Git 文档
...
) 与 2 点范围语法,^commit
(“不是”commit
),< code>commit^ (commit
的父级)等。进一步
git rebase
只是一堆连续的gitcherry-pick。请参阅我的其他答案(根据 Git,谁是“我们”,谁是“他们”?),我在其中展示,除此之外,我还绘制了一张 ASCII 绘图,展示了 git rebase 的工作原理及其作用。
git merge
式工作流程中,仅显示某人在其 PR(拉取请求)功能中拥有的唯一提交合并前的分支How to cherry-pick a single commit, multiple commits, or a range of commits
...onto your currently-checked-out branch:
1. to cherry-pick a single branch or commit named
commit
Examples:
2. to cherry-pick multiple commits
Note that you can cherry-pick any number of commit hashes at once, and in any order you want. They will simply be applied one-at-a-time, and in the order you specify. If any conflicts arise, you will have to resolve them one-at-a-time then use
git add my_file
thengit cherry-pick --continue
when done to continue the cherry-pick process.3. to cherry-pick a range of commits
I originally learned the basics of this style from the most-upvoted answer by @Eric Darchis here.
Notice that to cherry-pick a range of commits, you must specify a starting and ending commit hash, with
..
between them. However, in a range of commits, the beginning commit is NOT included. Therefore, to include it, you must specify the commit before the beginning commit. The syntax to specify the preceding commit is to put~
,~1
, or^
right after your commit, as in:beginning_commit~
, which means: "the commit right beforebeginning_commit
".Note:
commit~
,commit~1
, andcommit^
all mean "one commit prior tocommit
", or otherwise said: "the commit beforecommit
".To specify two commits prior to
commit
, you can use syntax like this:To specify three commits prior to
commit
, you can do this:This does NOT work:
This does work, but is a very special case. See also my Q&A: In a
git merge
-style workflow, show only the unique commits someone had in their PR's (Pull Request's) feature branch before merging:To test the above "previous commit syntax" concepts yourself, the easiest way is with the
git log
command. Ex:4. To cherry-pick a range of your peer's commits onto your branch
...when their branch
peer_branch
is forked off of an earlier version of your branchmy_branch
.Quick summary
The difference between 2 dots and 3 dots in a commit range is very significant.
git diff branch1...branch2
is the equivalent ofgit diff $(git merge-base branch1 branch2) branch2
. This is useful when you want to see the changes that have been made inbranch2
since it diverged frombranch1
, rather than the differences between the two branches in their current states. See my comment here and here and the answers here: What are the differences between double-dot ".." and triple-dot "..." in Git diff commit ranges?Full details and work-flow walk-through
Let's say you are working on your feature branch
my_branch
, and your peer wants to help make some changes for you to help you on your feature. You have already pushedmy_branch
to the remote namedorigin
. So, they are going to fetch your remote branch namedmy_branch
to their local computer, fork their own branch namedpeer_brach
off of it, then push to their own branch namedpeer_branch
. Once they do that, you will cherry-pick all of their additions at once. This is what the first part of this process looks like:Now that they have pushed all of their changes to remote
origin
as their own branch namedpeer_branch
, you can cherry-pick all of their commits they added on top of your work like this:For your understanding, that
cherry-pick
command just above, with 3 dots in it, is exactly equivalent to this longer command:The
git merge-base my_branch origin/peer_branch
part finds the common parent commit hash between branchmy_branch
and branchorigin/peer_branch
. This is the commit at which point they forked theirpeer_branch
off your yourmy_branch
. Then, you are, of course, cherry-picking the range of commits from that point to (..
) their final commit atorigin/peer_branch
.To read more about that 3-dot syntax, see here: What are the differences between double-dot ".." and triple-dot "..." in Git diff commit ranges? [duplicate]. For help on
git checkout -b new_branch from_branch
, see my answer here: Various ways to create a branch in git from another branchOfficial Git documentation
...
) vs 2 dot range syntax,^commit
("not"commit
),commit^
(the parent ofcommit
), etc.Going further
git rebase
is just a bunch of sequentialgit cherry-pick
s. See my other answer here (Who is "us" and who is "them" according to Git?) where I show, among other things, an ASCII drawing I made of how agit rebase
works and what it's doing.git merge
-style workflow, show only the unique commits someone had in their PR's (Pull Request's) feature branch before merging最简单的方法是使用
rebase
的onto
选项。假设当前在a
处结束的分支称为 mybranch,并且这是您要将c
-f
移动到的分支。The simplest way to do this is with the
onto
option torebase
. Suppose that the branch which current finishes ata
is called mybranch and this is the branch that you want to movec
-f
onto.或者所要求的一行:
Or the requested one-liner:
您可以使用
git rebase
和gitbranch
的串行组合将一组提交应用到另一个分支。正如 Wolfc 已经发布的那样,第一个命令实际上复制了提交。但是,在将分支名称添加到组的最顶层提交之前,更改不可见。请在新选项卡中打开图片...
以文本形式总结命令:
gitk --all &
。HEAD
。git分支选择
这应该可以澄清一些事情:
a
是该组的新根目标。b
是该组第一次提交之前的提交(不包括)。f
是该组的最后一次提交(含)。之后,您可以使用 git checkout 功能 && git reset --hard b 从
feature
分支中删除c
到f
的提交。除了这个答案之外,我还写了一个 博客文章 描述了另一个场景中的命令,应该有助于一般使用它。
You can use a serial combination of
git rebase
andgit branch
to apply a group of commits onto another branch. As already posted by wolfc the first command actually copies the commits. However, the change is not visible until you add a branch name to the top most commit of the group.Please open the picture in a new tab ...
To summarize the commands in text form:
gitk --all &
.git rebase --onto a b f
.HEAD
is marked.git branch selection
This should clarify things:
a
is the new root destination of the group.b
is the commit before the first commit of the group (exclusive).f
is the last commit of the group (inclusive).Afterwards, you could use
git checkout feature && git reset --hard b
to delete the commitsc
tillf
from thefeature
branch.In addition to this answer, I wrote a blog post which describes the commands in another scenario which should help to generally use it.
要应用 JB Rainsberger 和 sschaef 的评论来具体回答这个问题...要在此示例中使用樱桃选择范围:
或
To apply J. B. Rainsberger and sschaef's comments to specifically answer the question... To use a cherry-pick range on this example:
or
要从提交 ID 到分支尖端进行挑选,您可以使用:
To cherry pick from a commit id up to the tip of the branch, you can use:
另一个值得一提的变体是,如果您想要分支中的最后
n
提交,则~
语法可能会很有用:在这种情况下,上述命令将选择最后 4 个提交从名为
some-branch
的分支提交(尽管您也可以使用提交哈希来代替分支名称)Another variant worth mentioning is that if you want the last
n
commits from a branch, the~
syntax can be useful:In this case, the above command would pick the last 4 commits from a branch called
some-branch
(though you could also use a commit hash in place of a branch name)择优挑选多个提交:
签出到您想要择优挑选提交的分支
使用此命令:(通过部分哈希)
Cherry-pick multiple commits:
Checkout to your branch where you want to cherry-pick the commits
Use this command: (by partial hash)
实际上,最简单的方法可能是:
MERGE_BASE=$(git merge-basebranch-abranch-b)
将生成的分支重新设置为自身,从步骤 1 的合并基础开始,并手动删除不需要的提交:
或者,如果只有几个新提交,请跳过步骤 1,只需使用
在第一步中,使用足够的
^
移过合并基础。您将在交互式变基中看到类似的内容:
然后删除行 b (以及您想要的任何其他行)
Actually, the simplest way to do it could be to:
MERGE_BASE=$(git merge-base branch-a branch-b)
rebase the resulting branch onto itself, starting at the merge base from step 1, and manually remove commits that are not desired:
Alternatively, if there are only a few new commits, skip step 1, and simply use
in the first step, using enough
^
to move past the merge-base.You will see something like this in the interactive rebase:
Then remove lines b (and any others you want)
我需要优先选择从一个分支到另一个分支的提交,但这里的提交很难理解,希望下面的帮助可以帮助您解决一个简单的问题:下面
要执行的步骤:
。从“dev”分支
2 获取提交详细信息。将提交推送到“hotfix1”分支
要一次执行多个操作,只需在上面进行 1 处更改,请按顺序给出所有提交 ID:
I need cherry pick a commit from one branch to another on priority, but commits here were difficult to understand, hope below helps with a easy one:
Procedure to do below:
1 . Get commit details from "dev" branch
2 . Push the commit to "hotfix1" branch
To do multiple at once, only 1 change in the above, give all commit ids in sequence:
这是一个脚本,您只需告诉脚本樱桃选择的源分支和目标分支以及提交数量,即可连续选择多个提交:
https://gist.github.com/nickboldt/99ac1dc4eb4c9ff003a1effef2eb2d81
从分支中挑选到 master (使用当前分支作为源)
:从 6.19.x 分支中选择最新的 5 个提交到 master:
Here's a script that will allow you to cherry-pick multiple commits in a row simply by telling the script which source and target branches for the cherry picks and the number of commits:
https://gist.github.com/nickboldt/99ac1dc4eb4c9ff003a1effef2eb2d81
To cherry-pick from your branch to master (uses the current branch as source):
To cherry-pick the latest 5 commits from your 6.19.x branch to master:
或者使用GitHub桌面应用程序,
您可以在源分支的历史选项卡中多选提交,然后右键单击以获取选项“Cherry-Pick Selected Commits” 。
Alternatively using GitHub Desktop Application,
You can multi-select commits in the history tab of the source branch, then right-click to get the option "Cherry-Pick Selected Commits".
除了提交之外, 您可以通过管道输入来自标准输入的 SHA 列表。
rev-list
基本上是git-log
的 plumbing 命令(“丑陋”但快速的表弟)注意需要
--reverse
。您可以通过这种方式做更高级的事情,而不仅仅是提交范围。
In addition to commit-ish, you can pipe in a list of SHAs from stdin.
rev-list
is basically the plumbing command (the "ugly" but fast cousin) ofgit-log
NB that
--reverse
is needed.You can do more advanced stuff this way rather than simply a commit range.
这并不是关于如何挑选多个提交的真正答案,而是一种避免过多合并的方法。我使用 IntelliJ 完成了此操作,但在命令行上也应该很容易完成。
您可以在要从中挑选的第一个提交之前从最后一次提交创建一个临时分支。然后将您需要的所有内容挑选到这个临时分支中。这通常应该很容易,没有很多冲突。
然后压缩所有精选的提交。这会将所有来回更改变成单个更改。
现在将该单个提交合并到您的实际目标分支中。您不必多次解决冲突。
Not really an answer on HOW to cherry pick multiple commits but a way to avoid too much merging. I did this using IntelliJ but it should be easy to do on the command line as well.
You can make a temporary branch from the last commit just before the first one you want to cherry pick from. Then cherry pick everything you need into this temporary branch. This should generally be easy without many conflicts.
Then squash all the cherry picked commits. This will turn all the back and forth changes into single changes.
Now merge that single commit into your actual target branch. You will not have to resolve conflicts more than once.