8 git git-merge git-cherry-pick
所以我遇到了一种情况,我只想要来自 branchA 的特定提交,因为该分支中的其他提交尚未准备好合并。因此,如果我从 branchA 中挑选 commitX 到 master,然后将 branchA 合并到 master(假设中间有一些提交),就 git 历史而言,commitX 会发生什么?它是否因为它已经存在于 master 中而被忽略,或者是否发生了某种重复?
该git merge操作并不像“合并路径”那样查看单个提交。相反,它只查看开始和结束快照。但是请注意,有两个结束快照(一个开始):
...--o--B--o--...--o--L
\
o--...--o--R
Run Code Online (Sandbox Code Playgroud)
这里,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
Run Code Online (Sandbox Code Playgroud)
这意味着你的git cherry-pick是,“我们所做的”和“他们做了什么”可能包括一些相同的变化相同的文件,但是这是没有问题的,因为步骤git merge获得这两个后确实EN-集体的diff是合并更改,只获取出现在合并左侧和右侧“两侧”的任何更改的副本。
但是,假设您选择了一个提交,然后沿着一条路径再次将其还原,例如:
...--o--B--X'--!X'--L
\
X--o--R
Run Code Online (Sandbox Code Playgroud)
(X'有勾号的原因是它是 commit的副本X:当您挑选一个提交时,新副本会获得不同的哈希 ID。)
在这里,您X为分支(图中的下一行)编写了 commit in ,将其挑选到主行(上一行)中,意识到它尚未准备好或已损坏,将其还原(添加!X'),然后使L主线中的最终提交。现在,当您合并时,X进入然后再次退出的副本的事实是不可见的:Git 比较BvsL并且在所有X'--!X'序列中都看不到任何迹象。因此,它仍然需要一份由 commit 引入的更改X。
如果X在以 结尾的分支上提交已准备就绪R,则这是正确的操作。
如果提交X仍然失败,这是错误的操作——但正确的解决方法可能是X在合并之前恢复分支。
1除了find B,即:Git 必须从Land开始,并R通过图形向后工作以找到合并基础。这意味着 Git 必须遍历一些其他无趣的提交节点。