所以我遇到了一种情况,我只希望来自branchA的特定提交,因为该分支中的其他提交尚未准备好合并。因此,如果我从branchA中选择commitX到master,然后将branchA合并到master(之间有一些提交),那么就git历史而言,commitX会发生什么?是否会被忽略,因为它已经存在于master中,或者是否会发生某种重复?
答案 0 :(得分:3)
git merge
操作不会查看"合并路径"中的各个提交。相反,它只查看开始和结束快照。但请注意,两个结束快照(以及一个开始):
...--o--B--o--...--o--L
\
o--...--o--R
此处,B
是合并基础提交,L
和R
是左(或本地或--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会比较X
与B
并且看不到任何符号L
1}}序列。因此,它仍然需要提交X'--!X'
引入的更改的一个副本。
如果提交X
已在以X
结尾的分支上准备就绪,则这是正确的操作。
如果提交R
仍然被破坏,这是错误的操作 - 但正确的解决方法可能是在合并之前在分支上恢复X
。
1 除了查找X
之外,即:Git必须从B
和L
开始,然后通过图表向后查找合并库。这意味着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完全没有关系,稍后会合并。