了解 Git 历史记录简化

Azure DevOps Services | Azure DevOps Server 2020 | Azure DevOps Server 2019 | TFS 2018

Visual Studio 2022 |Visual Studio 2019 |Visual Studio 2017 |Visual Studio 2015

Git 历史记录简化可能是一种令人困惑的野兽。 99% 的时间你甚至不知道它存在, 但偶尔它会跳出 Git 的黑暗角落, 咬你。 在本文中,我们将探讨什么是历史记录简化,以及查看文件历史记录时如何引起混淆。

让我们从一个常见方案开始:

  1. 将更改推送到文件,然后将更改合并到 main 中。
  2. 你的一些同事还会将其分支合并到主分支。
  3. 你稍后会回来,并注意到你的更改缺失。
  4. 查找罪魁祸首,可查看文件历史记录并注意...你的更改甚至未列出!

Git 提交历史记录是一棵树。 有时,时间顺序历史记录与实际文件树历史记录不同。 当合并提交将文件还原回其原始状态时,通常会发生这种情况。 在这种情况下,默认历史记录视图 实际上不会显示所有更改,因为从技术上讲,文件没有更改。 在此方案中,Git 意识到它可以简化历史记录,并且最有可能要查找的“更改”将从日志中删除。

除非你以前遇到过,否则你可能会感到沮丧,想知道 我的改变在哪里?

历史记录简化:默认启用

默认情况下,在文件上运行日志命令: git log file.txt 将自动简化历史记录,可能隐藏其输出中的某些提交。 有关详细信息,请参阅 git 日志人页

令人困惑的是,如果只是运行git log,历史简化不会发生,因为你正在查看所有更改,没有什么可以简化的。

若要关闭历史记录简化,需要使用命令行开关 --full-history

历史简化示例

为了更好地了解这一工作原理,我们将创建自己的历史简化示例。 首先,让我们看看我们将创建的历史图:

Git Branches

如你所看到的,我们将:

  1. 创建一个文件。
  2. 在分支 (动物) 中添加一行。
  3. 在另一个分支中添加另一行, (水果) 。
  4. 将分支 动物 合并回主干。
  5. 将分支 水果 合并回主,并从水果分支中选择文件的完整副本。
  6. 检查文件的历史记录。

正如你所看到的,Git 将简化我们的历史记录。 此处的关键是步骤 5 - 我们忽略 了动物 分支的所有更改。 Git 会注意到,文件基本上 未在 步骤 1 和步骤 5 之间更改,因此它只会显示 两个历史记录条目

首先创建文件并将其添加到存储库:

> cd sample
> git init
> echo "some content" > test.txt
> git add test.txt
> git commit -m "Initial commit"

现在,我们决定将文本“donkeys”追加到动物分支中的文件中:

> git checkout -b animals
> echo "donkeys" >> test.txt
> git commit -am "We have added an animal"

在试验时,我们决定也许要改用文件中的水果,所以我们创建一个不同的分支,并在文件末尾追加文本“香蕉” :

> git checkout main -b fruit
> echo "bananas" >> test.txt
> git commit -am "We have added a fruit"

我们对我们的变化感到满意,我们决定将动物分支合并回主干:

> git checkout main
> git merge animals

现在,让我们看看文件 test.txt 日志:

> git log test.txt
    
    commit 6b33d99b996c430a60c9552b79245d1aa8320339
        Date:   Mon Feb 15 10:45:33 2016 -0500

        We have added an animal

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

到目前为止,这么好,对吗? 日志输出中什么都看不出普通值。 现在,假设我们改变了主意,并决定合并我们的水果分支:

>git merge fruit
    
    Auto-merging test.txt
    CONFLICT (content): Merge conflict in test.txt
    Automatic merge failed; fix conflicts and then commit the result.

Uh-oh,合并冲突。 经过一些考虑,我们决定从水果分支 使用整个 test.txt 文件 。 通常,你将使用某种文本编辑器或合并工具,但我们只会重新创建整个文件,因为它只有两行:

> echo "some content" > test.txt
> echo "bananas" >> test.txt
> git commit -am "Fixed merge conflict"

现在让我们看看文件 test.txt 历史记录:

> git log test.txt
    
    commit fdd4dfd816c4efebc5bdb240f49e934e299db581
        Date:   Mon Feb 15 10:51:06 2016 -0500

        We have added a fruit

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

当然,我们看不到日志中第一个试验的任何更改,也没有看到合并! 他们还在吗? Git 是否完全消除了更改?

> git log --full-history test.txt

正如你所看到的,尽管它简化了没有 full-history 标志的日志,但 Git 已保留所有更改:

> commit 5d0bb77a24e265dc154654fb3b5be331b53bf977
    Merge: 6b33d99 fdd4dfd
        Date:   Mon Feb 15 10:59:34 2016 -0500

        Fixed merge conflict

    commit fdd4dfd816c4efebc5bdb240f49e934e299db581
        Date:   Mon Feb 15 10:51:06 2016 -0500

        We have added a fruit

    commit 6b33d99b996c430a60c9552b79245d1aa8320339
        Date:   Mon Feb 15 10:45:33 2016 -0500

        We have added an animal

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

Git 历史记录简化摘要

关于历史简化的事情是,大多数时候你永远不会注意到它。 但是,当合并冲突出错并想知道发生了什么时,你可能会发现自己正在查看 git 日志历史记录,并想知道更改的位置。

现在,你知道:“现在,你不会惊慌失措:

  • 默认情况下打开文件的历史记录简化
  • 标志 --full-history 将为你提供更全面的文件历史记录

更新:由于我撰写了本文,Azure DevOps Services引入了许多令人敬畏的历史查看选项。 这意味着,如果你不想通过命令行进行日志处理,只需拉取要在资源管理器中查看历史记录的文件,你将看到以下历史记录筛选器,你可以在其中指定简单或非简单历史记录视图:

Git Filters

(c) 2016 Microsoft Corporation。 保留所有权利。 本文档“按原样”提供。本文档中表达的信息和视图(包括 URL 和其他 Internet 网站引用)可能会在不通知的情况下更改。 您自行承担其使用风险。

本文档未向您提供任何 Microsoft 产品中任何知识产权的任何合法权利。 可以复制本文档并将其用于进行内部参考。