我是 Git 新手。
我创建了一个新分支new_branch
。我已经在不同的分支中完成了所有更改和提交old_branch
。现在我想从分支中挑选一些提交old_branch
到new_branch
by git cherry-pick
。为此,我首先需要知道该分支中有哪些提交,然后选择它们并与new_branch
.
我怎样才能做到这一点?
我是 Git 新手。
我创建了一个新分支new_branch
。我已经在不同的分支中完成了所有更改和提交old_branch
。现在我想从分支中挑选一些提交old_branch
到new_branch
by git cherry-pick
。为此,我首先需要知道该分支中有哪些提交,然后选择它们并与new_branch
.
我怎样才能做到这一点?
git checkout new_branch
git log old_branch
日志将显示 old_branch 中的每个提交,并在提交消息上方显示一个长字符串,如“cf5e845a13866239eb87f2593d6edc6e273decc5”。这是提交哈希。然后你可以做
git cherry-pick <commit hash>
对于您想要的每个提交。我建议按时间顺序进行(从底部开始处理日志)。
有很多方法可以做到这一点,这里有几个提交清单:
git log --cherry new_branch..old_branch --oneline
将向您显示old_branch
无法从old_branch
.
或者另一种方式:
git checkout old_branch
git cherry new_branch --abbrev=6 -v
这将向您显示在old_branch
(没有引入相同更改的提交)内的提交,并将标记提交以指示它们是否-
已被选中,或者尚未“+”被挑选到new_branch
例如:
+2bdcd1 1st commit (Has not been cherry picked)
-8de6cc 2nd Commit (Has been cherry picked)
+8ac1ee 3nd Commit (Has not been cherry picked)
无论哪种情况,您都可以使用
git cherry-pick <commit>
尽管您想在第二种情况下检查“new_branch”。
@naomi 给出的方法可以正常工作,但是有一个更简单的方法。您的old_branch
分支从其他分支上的某个提交开始,如下所示:
A --- B --- C --- D <-- devel (let's say it's branch devel, anyway)
\
E - F - G - H <-- old_branch
您已经new_branch
从某个提交(可能是 B 或 C 或 D)创建了一个分支,并且您想挑选一些提交 E、F、G 和/或 H(可能是更长的提交字符串,但这应该说明事情)。
通常,如果您想获取未发布的工作序列(也许old_branch
就是这样一个序列)并将其“移动”到最新的(提交 D)之上,您只需执行以下操作:
$ git checkout old_branch # get onto old_branch
$ git rebase devel # and rebase it onto commit D in "devel"
这样做是制作提交 E 到 H 的“副本”,在“D”之后添加每个提交。然后它剥离标签old_branch
(用于命名提交 H)并将其粘贴到 H 的副本上,给出:
A --- B --- C --- D <-- devel
\ \
\ E' - F' - G' - H' <-- old_branch
\
E - F - G - H [abandoned, see footnote]
您想要的是选择一些提交,比如说 C(无论您在new_branch
上面创建什么)并做同样的事情,但不是“剥离标签” old_branch
。此外,您要选择 E、F、G 和 H 中的哪一个去那里。完成后,您希望new_branch
添加标签。这实际上真的很容易。不要在提交 C 处创建分支new_branch
,而是在提交 H 处创建它,即old_branch
:
$ git checkout old_branch; git checkout -b new_branch
现在new_branch
和old_branch
在内容方面相同,但名称不同。
现在您可以简单地rebase -i
(交互式,让您选择)new_branch
到您想要它去的点。我一直假设C
在这里提交,我一直假设这是从名为 的分支提示退一步devel
,所以我将使用它运行:
$ git rebase -i --onto devel~1 devel new_branch
在您选择rebase -i
允许的方式之后(并解决删除某些提交的任何冲突并git rebase --continue
在解决后继续),您最终会得到类似的结果,具体取决于您采取哪些提交以及删除哪些提交。我假设您删除 F 但保留其余部分:
A --- B --- C --- D <-- devel
\ \
\ E' - G' - H' <-- new_branch
\
E - F - G - H <-- old_branch
实际上,您只需两个命令(上面的 3 条)就可以完成所有这些操作,git branch
就像new_branch
在old_branch
. 此外,您很可能想要到任何分支rebase -i
的尖端,即,而不是变基,--onto devel~1
您只想变基到 (the tip of) devel
。--onto
在这种情况下,您毕竟不需要该部分:
$ git branch new_branch old_branch
$ git rebase -i devel new_branch
这里的结果几乎和以前一样,除了现在提交 E' 来自 D 而不是 C:
A --- B --- C --- D <-- devel
\ \
\ E' - G' - H' <-- new_branch
\
E - F - G - H <-- old_branch
这基本上是我在重新处理未发布的更改时所做的。如果我在(比如说)分支上,revise
我将它重命名为,在同一个地方revise-0
创建一个新的,然后稍微清理一下。经过一次之后,我可能会决定再次修改它,所以我重命名为并在与 相同的地方创建一个新的,然后再等等。如果我想要的话,我所有的旧刺仍然存在,直到我决定不想要它们;然后我删除所有 -0 -1 -2 ... 名称。revise
rebase -i
revise
revise-1
revise
revise-1
rebase -i
脚注:上面标记为“已放弃”的提交仍然存在——它们通过 reflog 阻止垃圾收集——但最终 reflog 条目过期并且它们在git gc
. 在那之前,它们大多是不可见的:例如git log --all
,gitk --all
不会显示它们。您可以使用 运行这些命令--reflog
,但即便如此,如果没有分支标签,它们仍然很难找到。我喜欢坚持一段时间,因此上面的多个分支名称工作流程。