如果我从分支中挑选一个提交然后合并整个分支,那么git历史会发生什么?

时间:2017-06-12 22:24:26

标签: git

所以我遇到了一种情况,我只希望来自branchA的特定提交,因为该分支中的其他提交尚未准备好合并。因此,如果我从branchA中选择commitX到master,然后将branchA合并到master(之间有一些提交),那么就git历史而言,commitX会发生什么?是否会被忽略,因为它已经存在于master中,或者是否会发生某种重复?

2 个答案:

答案 0 :(得分:3)

git merge操作不会查看"合并路径"中的各个提交。相反,它只查看开始和结束快照。但请注意,两个结束快照(以及一个开始):

...--o--B--o--...--o--L
         \
          o--...--o--R

此处,B是合并基础提交,LR是左(或本地或--ours)和右(或其他,远程,或{ {1}})分别提交。同时每一轮--theirs代表Git甚至没有看到的一些提交。 1 Git只是这样做,实际上是:

o

这对您的git diff --find-renames B L # figure out what we did git diff --find-renames B R # figure out what they did 意味着什么"我们做了什么"和"他们做了什么"可能包含对相同文件的一些相同的更改 - 但这没有问题,因为git cherry-pick在获取这些文件后所做的步骤两个en-masse差异是组合这些变化,只取得左右两侧出现的任何变化的一个副本"合并。

但是,假设你挑选一个提交,然后沿着一条路径再次恢复它,例如:

git merge

...--o--B--X'--!X'--L \ X--o--R 有勾选标记的原因是它提交了X'副本:当您挑选提交时,新副本会获得不同的哈希ID。)

在这里,你为分支(图中的下面一行)编写了提交X,将其挑选到主线(上面一行),意识到它没有准备好或被打破,< em>还原(添加X),然后在主线中进行最终提交!X'。现在,当您合并时,L的副本进入,然后再次出去的事实是不可见的:Git会比较XB并且看不到任何符号L 1}}序列。因此,它仍然需要提交X'--!X'引入的更改的一个副本。

如果提交X已在以X结尾的分支上准备就绪,则这是正确的操作。

如果提交R仍然被破坏,这是错误的操作 - 但正确的解决方法可能是在合并之前在分支上恢复X

1 除了查找X之外,即:Git必须从BL开始,然后通过图表向后查找合并库。这意味着Git必须遍历一些其他无趣的提交节点。

答案 1 :(得分:1)

没有特别的事情发生,但让我们分解。

         M
-o---o---o master
  \
   \----o--o--o branchA
           X

现在你做樱桃挑选。那么情况是:

         M  MX
-o---o---o--o master
  \
   \----o--o--o branchA
           X

到目前为止一切顺利。然后你再做几次提交......

         M  MX
-o---o---o---o---o---o---o master
  \
   \----o---o---o---o---o---o branchA
            X

现在合并......

         M  MX
-o---o---o---o---o---o---o-----o master
  \                           /
   \----o---o---o---o---o---o branchA
            X

所有这一切都像往常一样。 Git没有存储提交MX是挑选结果的事实,并且它不需要。 cherry-pick操作与合并的不同之处在于,挑选的提交X和新的提交MX彼此之间没有任何关系。它们也不可能,因为(通过合并)“父子关系”具有最终master包含所有 branchA历史的语义,不仅如此这个改变引入了一次提交。

在文件级别上的实际更改就像您手动编辑它们一样。也就是说,如果master中的樱桃选择引入了更改,git会注意到(通过在相关线路上合并期间没有注意到任何差异,在简单的情况下)并且事情将被合并。 / p>

编辑:关于你在评论中提出的问题......

  

让我说我的commitX有一条消息“Foobarbaz”。鉴于这个场景,我现在在我的主分支中有两个提交,提交消息“Foorbarbaz”或只有1个。

每次提交在提交级别都有一个消息,在文件级别有一些内容。樱桃选择仅在内容级别 ;也就是说,它从一次提交中获取文件更改,并将其应用于您当前工作目录中的任何内容。可能令人困惑的是,在应用该更改后,命令git cherry-pick确实为您创建了一个新提交(在此示例中为MX)。这个新提交只是一个普通的提交 - 它与原始提交X无关,除了git cherry-pick复制旧提交消息(您可以编辑)以方便。

作为澄清,您可以执行git cherry-pick -n并避免git为您执行提交 - 这将使您有机会在自己提交之前编辑任何樱桃选择。

所以,樱桃选择实际上只是一种方便的方法,就像你自己编辑了变化并自己承诺一样。新提交消息可能与旧提交消息相似或相等的事实与git完全没有关系,稍后会合并。