在分支中将提交合并在一起



我是Git的新手。

我创建了一个新的分支new_branch。我已经在不同的分支old_branch中完成了所有更改和提交。现在,我想通过git cherry-pick从分支old_branch选择一些提交到new_branch。为此,我首先需要知道该分支中有哪些提交,然后选择它们并与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(用于命名commit 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_branchold_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可以在与old_branch相同的点创建new_branch。此外,您可能希望将rebase -i添加到任何分支的尖端上,也就是说,与其将--onto devel~1重新定基,不如将其重新定基到(的尖端)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,在同一位置创建一个新的revise,然后rebase -i并稍微清理一下。经过一次之后,我可能会决定再次修改它,所以我将revise重命名为revise-1,并在与revise-1相同的位置创建一个新的revise,然后再次创建rebase -i,等等。如果我想要它们,我所有的旧刺都还在,直到我决定不想要它们;然后我删除所有-0-1-2。。。姓名。


脚注:上面标记为"已放弃"的提交仍然存在——它们通过reflog保留以防止垃圾收集——但最终reflog条目过期,它们在git gc中消失。在那之前,它们大多是不可见的:例如,git log --allgitk --all不会显示它们。您可以使用--reflog运行这些命令,但即使在没有分支标签的情况下,它们仍然有点难以找到。我喜欢把它们挂一段时间,因此上面有多个分支名称的工作流。

相关内容

  • 没有找到相关文章

最新更新