合并后Git提交丢失
我们有3家分公司(A、B、C),如下所示:合并后Git提交丢失,git,Git,我们有3家分公司(A、B、C),如下所示: ---\--A1--\------Am------Merge1---An---Merge2--- \ \ / / \ \--C1---C2---/ / \ / \--B1--------------Bn---------/ 问题出现在Merge2。分支C上
---\--A1--\------Am------Merge1---An---Merge2---
\ \ / /
\ \--C1---C2---/ /
\ /
\--B1--------------Bn---------/
问题出现在Merge2。分支C上的一些提交(不是全部,而是一些,比方说C2)在Merge2之后在分支A上丢失,这在Merge1和Merge2之间存在
执行Merge2时,只有一个文件冲突,与丢失的提交(C2)无关。我们解决了冲突并成功地完成了合并
似乎C2被分支A上的Merge2逆转,没有任何日志。
发生了什么事?出现这种情况的原因可能是什么?您的意思不是提交本身丢失,而是在提交过程中(对某些文件)所做的更改已恢复(未进行) 这里值得注意的是,提交并不是真正“更改”文件。相反,每次提交都存储一组完整的文件,完整无缺。当您要求Git向您显示一些提交时(假设其ID为
c2c2c2…
):
Git所做的是:
c2c2c2…
c2c2…
Am
和C2
都出现在“Merge1
之前”。也就是说,commitMerge1
有两个父提交
如果您要求Git显示提交Merge1
,它应该与哪个父级进行比较
这就是事情变得特别奇怪的地方。两个命令gitlog-p
和gitshow
看起来非常相似。事实上,它们非常相似。一个明显的区别是git log-p
显示多个提交,而git show
只显示您告诉它显示的一个提交。您可以运行git log-n1-p
只显示一个提交,现在看起来它们完全一样
他们不是
当您在合并提交中使用git show
时,git试图通过同时对两个父级进行比较来解决“要比较的提交”问题。由此产生的差异称为组合差异
但是,当您在合并提交中使用git log-p
时,git只是伸出隐喻之手,说“我无法显示针对两个父项的补丁”,然后放弃并继续下一次提交换句话说,git log-p
甚至懒得尝试使用diff进行合并。
但是等等,还有更多
现在,在本例中,您可能想知道是否可以在两个合并上,特别是在Merge2
上,使用git show
,从提交c2c2…
中找出文件发生了什么情况,其中更改得到了恢复。但是默认情况下,gitshow
会生成一个组合的diff,而组合的diff会故意忽略很多diff输出。特别是,一个组合的差异
假设从C2
恢复更改的文件是filef2
。从图中可以看出,Merge2
的两个父项是An
(它有f2
您想要的方式)和Bn
(它没有)
这里实际发生的是,在创建
Merge2
的合并过程中,您不知何故告诉Git使用commitBn
中的f2
版本。也就是说,Merge2
中的文件f2
与Bn
中的文件f2
完全相同,与提交中的f2
不同
如果使用git show
查看Merge2
,组合的差异将跳过f2
,因为它与Bn
中的f2
相同
同样的道理,更糟糕的是,对于git log-p
:它完全跳过了合并,因为显示差异太难了
即使没有-p
,当您请求“文件更改”时,git log
也会做同样的事情,完全跳过合并。这就是为什么在日志输出中看不到它
(顺便说一句,git log master--f2
从不显示commitC2
本身的原因是在git log
的选项中添加文件名会打开“历史简化”在我认为有点冒牌行为的情况下,Git会把太多的历史简化掉,这样它就不会显示提交“代码> C2 < /代码>。在<代码>之前添加<代码>完整的历史< /代码> F2 < /代码>将代码> C2 < /代码>恢复到所示的一组提交。但是,合并仍然没有,因为<代码> Git日志跳过它。
如何看待变化
有一个解决办法。git show
和git log
都使用了一个额外的标志,-m
,它“拆分”合并。也就是说,它们不会将Merge2
视为合并提交,而是将合并分解为两个“虚拟联合体”
$ git show c2c2c2