git:如何移动分支的根2提交回来

时间:2017-04-20 22:53:22

标签: git rebase

我们说我有:

A - B - C - D - E - F  master
            \ 
             \- G - H  new feature branch

现在我意识到实际提交B和C. 属于新功能,所以我想将它们移到"新功能分支"。换句话说,我想要"新功能分支"从A开始,包括提交B和C:

A - D - E - F  master
 \ 
  \- B - C - G - H  new feature branch

我该怎么做?从我所读过的内容来看,似乎rebase是我正在寻找的功能,但在我搞砸我的存储库之前,我想确定一下。

(我已经搜索过并发现了很多非常相似的问题和例子,但没有一个像我所描述的情景那样完全,所以我是要求确定(毕竟,回购是毁灭的宝贵财富))。

3 个答案:

答案 0 :(得分:6)

Edmundo's answer是正确的(并且已经投票),但值得指出一些额外的项目。

首先,你的问题是关于"移动分支的根源"但这是Git;分支机构不会拥有根,而不是你想的方式。让我们看一下你的图形绘图:

A - B - C - D - E - F  master
            \ 
             \- G - H  new feature branch

我认为你,就像我第一次使用Git时一样,想将提交A-B-C-D-E-F视为master分支,并提交G-H作为特色分支。但这并不是Git的工作方式。让我们重新绘制它,而不更改任何提交链接:

           E--F   <-- master
          /
A--B--C--D
          \
           G--H   <-- feature

这应该更清楚一点,就Git而言,提交A-B-C-D两个分支上。只有一个根。该提交A:它是一个根,因为它没有父提交,从提交到父级的链中没有向后链接。

其次,无论你怎么做,最终都要复制一些提交。原因是每个提交的父ID都是该提交的标识的一部分。 &#34;真名&#34;任何提交都是它的哈希ID,哈希ID是通过读取提交的完整内容构建的:源代码树,提交消息,作者姓名和日期等,但也总是包含父ID。 1 < / sup>您希望最终的图形类似于:

  D--E--F   <-- master
 /
A
 \ 
  B--C--G--H   <-- feature

但现有的D链接(或点)返回到现有的C,而不是A,现有的G指向现有的D }}

这就是为什么樱桃选择有效:git cherry-pick本质上复制提交。新副本&#34;做同样的事情&#34;作为原作,但某事不同,即使它像&#34一样简单;我的父母是......&#34;。 (通常它也有一个不同的附加对象,只是它与更改所做的,与其新的父对象相比,是相同的将原稿与原始父母进行比较时原稿的更改。这意味着you can't actually get what you want, just what you need

  D'-E'-F'  <-- master
 /
A
 \ 
  B--C--G'-H'  <-- feature

其中小刻度标记表示结果是原件的副本

原件会怎么样?答案是:如果您需要它们,它们仍然存在于存储库中。全貌更像是这样:

    D'-E'-F'   <-- master
   /
  /        E--F   [abandoned]
 /        /
A--B--C--D
       \  \
        \  G--H   [abandoned]
         \
          G'-H'   <-- feature

虽然git cherry-pick有效,git rebase - 特别是git rebase -i - 的作用是以花哨的自动方式完成这些副本,最后一步是移动分支名称,放弃原始版本提交。所以git rebase -i有时候是更容易的方式。

如果你运行git rebase -i,你会看到所有pick个命令,而这些命令实际上就是git cherry-pick:它确实在做一系列的挑选。如果您自己进行这些操作,可能会更清楚地发生了什么,并且您可以更好地控制分支标签的移动时间。

1 对于合并提交,这是父 s ,复数。所有的父母都参与哈希。

答案 1 :(得分:3)

修复主人:

git checkout A
git cherry-pick master~3..master # apply the changes we actually want to keep on master
git branch -f master # reposition master on new position
git checkout master

从功能分支中删除提交D:

git checkout feature-branch~3 # or git checkout C
git cherry-pick feature-branch~2..feature-branch # apply the last 2 revisions
git branch -f feature-branch
git checkout feature-branch

答案 2 :(得分:3)

您可以使用git rebase执行此操作。

首先,让我们来自master的一些提交:

$ git checkout master
$ git rebase --onto A C

这会将所有提交范围从C转移到master(但不包括C本身)到提交A上。

现在重新定义feature但抛出提交D:

$ git checkout feature
$ git rebase --onto C D

与上一个命令类似,这会将提交范围从D到feature(不包括D本身)移到C上。