缺少文件历史记录中的行删除(git) [英] Missing deletion of lines in file history (git)

查看:71
本文介绍了缺少文件历史记录中的行删除(git)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用git进行源代码控制.

We are using git for source control.

如果我查看特定的文件历史记录(使用git log --pretty=format:"%h %ad" --date=short <filename>),会看到类似的内容:

If I take a look at particular file history (using git log --pretty=format:"%h %ad" --date=short <filename>), I see something like it:

HashOfCommitA 2018-01-15
HashOfCommitB 2018-01-09
HashOfCommitC 2018-01-05
<older commits>

CommitA和CommitB是合并提交.

The CommitA and CommitB are merge commits.

在CommitB(git diff HashOfCommitB <filename>)的更改中,在文件中添加了两行. 在CommitA的更改中,这些行不会受到影响,但是如果我在CommitA合并后检查文件内容,那么会丢失在CommitB中添加的两个新行.

In the changes of CommitB (git diff HashOfCommitB <filename>) there are two new lines added to file. In the changes of CommitA those lines aren't affected, but if I examine file content after CommitA merge, then two new lines added in CommitB are missing.

基本上,当我查看文件历史记录时,我可以看到一点点,其中添加了一些内容,但是在下一次提交后,它丢失了,并且在提交更改中我看不到此行的删除.

Basically, when I looking at file history, I can see at one point, that something is added, but after next commit, it's missing and I don't see the deletion of this lines in commit changes.

可能是因为合并是使用较旧版本的分支(没有CommitB)进行的?如何找到这些行的删除位置?

Might it be because merge was made with an older version of a branch (without CommitB)? How can I find where those lines were deleted?

换句话说,这怎么可能?将来有什么好的方法可以防止这种情况发生?

In other words, how is it possible? Are there good ways to prevent such situation in the future?

推荐答案

相关: Git;合并后代码消失了.要特别注意行为不佳的工具,这些工具可以很容易地使合并冲突的一个方面"不加思索.通常,避免此问题的一种好方法是在接受每个提交之前对每个提交进行彻底的测试.

Related: Git; code disappeared after merge. Pay particular attention to badly-behaved tools that make it very easy to keep only one "side" of a merge conflict without thinking. As a very general rule, a good, reliable way to avoid the problem is to have thorough tests that you run on each commit before accepting it.

如果我查看特定的文件历史记录...

If I take a look at particular file history ...

在这里要小心. Git没有文件历史记录;您所看到的是由Git选择特定的提交导致的伪造的伪历史-提交历史,而完整的提交集是存储库中实际上唯一的历史-作者git log的选择将是一个很好的过滤选择.当您使用这种过滤时,git log默认情况下会启用其称为 History Simplification 的功能,在

Be careful here. Git doesn't have file history; what you are seeing is a faked-up pseudo-history resulting from Git selecting particular commits—the commits are the history, and the complete set of commits is the only history actually inside the repository—that the authors of git log thought would be a good filtered-down selection. When you use this kind of filtering, git log enables, by default, what it calls History Simplification, which is described (rather poorly in my opinion) in this section of the documentation. I find that this can be quite misleading.

此外,除非您使用--graph,否则对git log的输出进行排序和显示,使得难以或有时甚至无法分辨哪些提交实际上发生在哪个点上.这里存在一个基本问题,即以线性顺序显示基本上不是线性的:

Besides that, unless you use --graph, the output from git log is sorted and displayed in a way that makes it difficult or sometimes impossible to tell which commits really happened at which points. There is a basic problem here with showing, in a linear order, that which is fundamentally not linear:

       B--C
      /    \
...--A      F--G   <-- branch-tip
      \    /
       D--E

在这里,提交G显然排在最后,所以这是Git首先向您显示的内容.接下来是Commit F(即,紧接在G之前),因此Git会向您显示F下一个.但是现在,Git可以向您显示 C E.应该选哪一个?

Here, commit G clearly comes last, so that's the one Git will show you first. Commit F comes next (i.e., just before G) so Git shows you F next. But now Git could show you either C or E. Which one should it pick?

Git的默认设置是在 commit time 之前使用它们,因此,如果C发生在E之后不久,Git将在此处显示C.然后很可能接着发生了E,以Git向后的方式(即,更早)发生了,所以Git现在显示E;现在Git可以显示BD.一旦显示出来,它就可以显示另一个或A,但是接下来另一个(BD)可能是 ,除非提交的时间设置错误,或在另一台对正确时间有不同想法的计算机上.

Git's default is to take them by commit time, so if C happened slightly after E, Git will show you C here. Then probably E happened next, in the Git-backwards fashion (i.e., earlier), so Git now shows E; now Git can show B or D. Once it's shown that, it can show the other or A, but the other (of B or D) is probably next, unless the commits were made with the time set wrong, or on another computer with a different idea of the correct time.

最终,您确实会看到所有的提交-除非 ,也就是说,简化历史记录"已删除了某些分支机构,也许是整个分支机构. (即使没有历史记录简化"功能,有时也很难预测它们的显示顺序.)更糟糕的是,在默认的历史记录简化"模式下,如上述链接的(可能无法理解的)文档所述:

Eventually, you do see all of the commits—unless, that is, History Simplification has been removing some, perhaps entire arms of branches. (Even without History Simplification, the order they are displayed in is sometimes hard to predict.) Worse, in the default History Simplification mode, as the (perhaps impenetrable) documentation linked above mentions:

如果提交是合并,并且对一个父对象是TREESAME,则仅跟随该父对象. (即使有几个TREESAME父母,也只能跟随其中一个.)否则,请跟随所有父母.

If the commit was a merge, and it was TREESAME to one parent, follow only that parent. (Even if there are several TREESAME parents, follow only one of them.) Otherwise, follow all parents.

在您的情况下,您将获得默认模式,因此,如果合并的作者选择了分支的一个一侧"(故意不从另一侧进行更改),则Git会完全修剪另一侧.但这正是您认为应该保留的更改被删除的地方,因此git log实际上对您说谎!

In your case, you are getting the default mode, so if the author of the merge picked one "side" of a branch (deliberately not taking changes from the other side), Git prunes the other side entirely. But that's precisely where the changes that you think should have been kept, were dropped, so git log has in effect lied to you!

我也将添加它,尽管这可能仅与之相关:

I will add this as well, although this may only be slightly relevant:

CommitA和CommitB是合并提交.

The CommitA and CommitB are merge commits.

(这意味着这些是至少有两个父母(可能恰好有两个父母)的提交.)

(This means that these are commits with at least two parents, probably with exactly two parents.)

在CommitB(git diff HashOfCommitB <filename>)的更改中...

In the changes of CommitB (git diff HashOfCommitB <filename>) ...

如果您正以这种方式运行该命令,则要求Git将存储在合并(合并结果)中的内容与当前工作树中的内容进行比较.这是 git diff文档的说明部分.因此,这些不是合并提交中存储的更改.

If you're running that command in exactly that way, you are asking Git to compare what's stored in the merge (the merge result) to what's in the current work-tree. That's the fourth form of git diff in the description section of the git diff documentation. So these are not changes stored in the merge commit.

实际上,合并提交中没有存储任何实际更改.以这种方式,合并提交就像任何其他提交一样:它存储快照,无论如何,在Git的眼睛"中,快照只是合并的正确结果(无论谁告诉Git,运行git merge,正确性证明是运行git merge的人提交了结果).该合并具有多个输入(通常是(两个)父级加上他们的(单个)合并基数),您可以将最终的合并快照与两个父级中的任何一个进行比较,因此查找会有所更改,但是这些更改您发现针对父级1的更改与您针对父级2的更改不同.

In fact, though, no actual changes are stored in the merge commit. The merge commit is, in this way, like any other commit: it stores a snapshot, which—in Git's "eyes" anyway—is simply the correct result of the merge (as told to Git by whoever ran git merge, with the proof of correctness being that whoever ran git merge committed the result). That merge has multiple inputs—typically, the (two) parents plus their (single) merge base—and you can compare the final merge snapshot to either of the two parents and hence find changes, but the changes you find with respect to parent #1 are different from the changes you find with respect to parent #2.

这篇关于缺少文件历史记录中的行删除(git)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆