我们正在使用git进行源代码控制。
如果我查看特定的文件历史记录(使用git log --pretty=format:"%h %ad" --date=short <filename>
),我会看到类似的内容:
HashOfCommitA 2018-01-15
HashOfCommitB 2018-01-09
HashOfCommitC 2018-01-05
<older commits>
CommitA和CommitB是合并提交。
在CommitB(git diff HashOfCommitB <filename>
)的更改中,有两个新行添加到文件中。
在CommitA的更改中,这些行没有受到影响,但是如果我在CommitA合并之后检查文件内容,那么在CommitB中添加的两个新行将丢失。
基本上,当我查看文件历史记录时,我可以在某一点上看到添加了某些内容,但在下一次提交后,它已丢失,我在提交时看不到删除这些行变化。
可能是因为合并是使用旧版本的分支(没有CommitB)?如何找到这些行被删除的位置?
换句话说,怎么可能?有没有很好的方法来防止将来出现这种情况?
答案 0 :(得分:1)
相关:Git; code disappeared after merge。特别注意表现不佳的工具,这样可以很容易地只保留一个&#34; side&#34;没有思考的合并冲突作为一般规则,避免问题的一种好的,可靠的方法是在接受之前对每次提交进行彻底的测试。
如果我查看特定的文件历史记录......
这里要小心。 Git没有拥有文件历史记录;您所看到的是由Git选择特定提交而产生的假伪历史 - 提交 历史记录,而完整的提交集是实际存储库中唯一的历史记录 - 作者git log
认为是一个很好的过滤选择。当您使用此类过滤时,默认情况下,git log
会启用它所称的历史简化,这在this section of the documentation中有所描述(在我看来相当糟糕)。我发现这可能会产生误导。
除此之外,除非您使用--graph
,否则git log
的输出将被排序和显示,这使得很难或有时无法确定哪些提交确实发生在哪些点上。这里存在一个基本问题,即以线性顺序显示基本上不是线性的:
B--C
/ \
...--A F--G <-- branch-tip
\ /
D--E
这里,提交G
显然是最后的,所以Git会先显示给你。接下来会提交F
(即G
之前),因此Git会向您显示F
。但现在Git可以向您显示 <{em> C
或 E
。它应该选哪一个?
Git的默认设置是提交时间,因此如果在C
之后E
稍微发生,Git会在此显示C
。那么接下来可能会发生E
,以Git向后的方式(即更早),所以Git现在显示E
;现在Git可以显示B
或D
。一旦显示,它可以显示另一个或A
,但另一个(B
或D
)可能接下来,除非提交是在时间设置错误的情况下进行的,或者是在另一台对正确时间有不同想法的计算机上进行的。
最终,你确实看到了所有的提交 - ,除非,也就是说,历史简化已经删除了一些,也许是整个分支机构。 (即使没有历史简化,它们显示的顺序有时很难预测。)更糟糕的是,在默认的历史简化模式中,上面提到的(可能是难以理解的)文档提到:
如果提交是合并,并且它是一个父级的TREESAME,则只关注该父级。 (即使有几个TREESAME父母,也只能跟随他们中的一个。)否则,请跟随所有父母。
在您的情况下,您将获得默认模式,因此如果合并的作者选择了一个&#34; side&#34;一个分支(故意不从另一方改变),Git完全修剪另一方。但是,这正是您认为应该保留的变更的确切位置,因此git log
实际上对您撒谎了!
我也会加上这个,虽然这可能只是略微相关:
CommitA和CommitB是合并提交。
(这意味着这些是至少有两个父母的提交,可能只有两个父母。)
在CommitB的更改中(
git diff HashOfCommitB <filename>
)...
如果您以这种方式运行该命令,那么您要求Git将合并中存储的内容(合并结果)与当前工作树中的内容进行比较。这是the description section of the git diff
documentation中git diff
的第四种形式。因此,这些不是存储在合并提交中的更改。
实际上,合并提交中没有存储实际的更改。以这种方式,合并提交就像任何其他提交一样:它存储快照,在Git&#34;眼睛&#34;无论如何 - 只是合并的正确结果(正如运行git merge
的任何人告诉Git一样,正确性的证据是任何运行git merge
的人都提交了结果)。该合并有多个输入 - 通常是(两个)父项加上它们(单个)合并基础 - 您可以将最终合并快照与两个父项中的任何一个进行比较,从而查找更改,但更改您发现父母#1与父母#2相关的更改不同。