我有一个这样的情况,只想要branchA中的一个特定提交,因为该分支中的其他提交还没有准备好合并。所以,如果我将commitX从branchA 挑选到 master 中,然后稍后将branchA与master合并(其中有一些提交在其中),那么就git历史而言,commitX会发生什么?它会被忽略,因为它已经存在于master中,还是会出现某种重复?
我有一个这样的情况,只想要branchA中的一个特定提交,因为该分支中的其他提交还没有准备好合并。所以,如果我将commitX从branchA 挑选到 master 中,然后稍后将branchA与master合并(其中有一些提交在其中),那么就git历史而言,commitX会发生什么?它会被忽略,因为它已经存在于master中,还是会出现某种重复?
...--o--B--o--...--o--L
\
o--...--o--R
在这里,B
是合并基础提交,L
和R
分别是左侧(或本地或--ours
)和右侧(或其他、远程或--theirs
)提交。同时,每个回合的o
代表Git甚至不查看的某些提交。1 Git实际上只执行以下操作:
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'
带有勾号的原因是它是提交X
的一个副本:当您挑选了一个提交时,新复制将获得不同的哈希标识符。)X
,将其挑选到主线(上方的线),意识到它并不准备好或已损坏,进行了还原(添加了!X'
),然后在主线中进行了最终提交L
。现在,在合并时,提交X
的一个副本进入然后又出现的事实是看不见的:Git将B
与L
进行比较,并且完全没有X'--!X'
序列的迹象。因此,它仍然需要提交X
引入的更改的一份副本。X
在以R
结尾的分支中已成为准备就绪状态,则这是正确的操作。X
仍然存在问题,则这是错误的操作,但正确的治疗方法可能是在合并之前还原分支上的X
。
B
外,也就是说:Git 必须从 L
和 R
开始并向后遍历图形以找到合并基础。这意味着 Git 必须遍历一些其他不相关的提交节点。没有特别的事情发生,但让我们来分解一下。
M
-o---o---o master
\
\----o--o--o branchA
X
现在你需要进行cherry-pick操作。然后情况会变成:
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
MX
是樱桃拣选的结果,也不需要。樱桃拣选操作与合并的区别在于,选择的提交X
和新提交MX
之间没有任何关系。它们也不能有,因为(通过合并)“父子”关系的语义是最终master
包含branchA
的所有历史记录,而不仅仅是单个提交引入的更改。master
中保持不变,则Git将注意到这一点(在简单情况下,在相关行上合并时不会注意到任何差异),然后进行合并。master
开始,我们回顾了顶部行上的两个提交(因为在该方向上从合并返回连接)和底部行上的两个提交(因为在那里有第二个连接)。因此,我们发现MX和X都包含在master
中。这使得Git与许多其他版本控制系统根本不同,在Git中,包含提交的分支集合会更改! - torek
gitk
所做的那样,大多数GUI都会这样做,当然我上面也是这样做的)的查看器将向您显示这两个提交位于稍后合并的不同开发线中。 - torek