Close

git diff


比对功能接受两个输入数据集并输出它们之间的变更。git diff 是一个多用途 Git 命令,它在执行时会在 Git 数据源上运行比对功能。这些数据源可以是提交、分支、文件等。本文档将讨论 git diff 的常见调用和比对工作流模式。git diff 命令通常与 git statusgit log 一起使用,用于分析 Git 代码存储库的当前状态。

读取比对:输出


原始输出格式

以下示例将在一个简单的代码存储库中执行。代码存储库是使用以下命令创建的:

$:> mkdir diff_test_repo
$:> cd diff_test_repo
$:> touch diff_test.txt
$:> echo "this is a git diff test example" > diff_test.txt
$:> git init .
Initialized empty Git repository in /Users/kev/code/test/.git/
$:> git add diff_test.txt
$:> git commit -am"add diff test file"
[main (root-commit) 6f77fc3] add diff test file
1 file changed, 1 insertion(+)
create mode 100644 diff_test.txt

如果我们此时执行 git diff,则不会有输出。这是可以预见的,因为比对代码存储库没有变更。创建代码存储库并添加了 diff_test.txt 文件后,我们可以变更该文件的内容以开始尝试比对输出。

Git 分支
相关资料

Git 分支

Bitbucket 徽标
查看解决方案

了解 Bitbucket Cloud 的 Git

$:> echo "this is a diff example" > diff_test.txt

执行此命令将变更 diff_test.txt 文件的内容。修改后,我们可以查看比对并分析输出。现在执行 git diff 将生成以下输出:

diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

现在我们来看看比对输出的更详细细分。

1. 比较输入

diff --git a/diff_test.txt b/diff_test.txt

此行显示比对的输入源。我们可以看到 a/diff_test.txtb/diff_test.txt 已被传递给比对。

2. 元数据

index 6b0c6cf..b37e70a 100644

此行显示一些内部 Git 元数据。您很可能不需要此信息。此输出中的数字对应于 Git 对象版本哈希标识符。

3. 变更标记

--- a/diff_test.txt
+++ b/diff_test.txt

这些行是为每个比对输入源分配符号的图例。在这种情况下,来自 a/diff_test.txt 的变更用 --- 标记,而来自 b/diff_test.txt 的变更则用 +++ 符号标记。

4. 比对区块

剩下的比对输出是比对“区块”的列表。比对仅显示文件中变更的部分。在我们当前的示例中,我们只有一个区块,因为我们正在处理一个简单的场景。区块有自己的精细输出语义。

@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

第一行是区块标头。每个区块前面都有一个包含 @@ 符号的标头。标头的内容是对文件所做变更的摘要。在我们的简化示例中,我们有 -1 +1,表示第一行发生了变更。在更真实的比对中,您会看到一个标头,如下所示:

@@ -34,6 +34,8 @@

在此标头示例中,从第 34 行开始提取了 6 行。此外,从第 34 行开始,还添加了 8 行。

比对区块的其余内容显示最近的变更。每个变更的行前面都有一个 +- 符号,表示变更来自哪个版本的比对输入。正如我们之前讨论的那样,- 表示与 a/diff_test.txt 相比发生的变更,+ 表示与 b/diff_test.txt 相比发生的变更。

突出显示变更


1. git diff --color-words

git diff 还有一个特殊模式,用于以更好的粒度突出显示变更:-‐color-words。此模式按空格对添加和删除的行进行标记,然后比对这些行。

$:> git diff --color-words
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
this is agit difftest example

现在,输出仅显示已变更的用颜色编码的字。

2. git diff-highlight

如果您克隆 git 源代码,就会发现一个名为 contrib 的子目录。它包含了一大堆与 git 相关的工具以及其他尚未升级为 git core 的有趣内容。其中一个是名为 diff-highlight 的 Perl 脚本。diff-highlight 将匹配的比对输出行配对,并突出显示已变更的子字片段。

$:> git diff | /your/local/path/to/git-core/contrib/diff-highlight/diff-highlight
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

现在,我们已经将比对缩减到尽可能小的变更。

比对二进制文件


除了我们到目前为止演示的文本文件实用程序外,git diff 还可以在二进制文件上运行。不幸的是,默认输出不是很有用。

$:> git diff
Binary files a/script.pdf and b/script.pdf differ

Git 确实有一个功能,允许您在执行比对之前指定一个 shell 命令将二进制文件的内容转换为文本。不过,它确实需要一些设置。首先,您需要指定一个 textconv 筛选器,描述如何将某种类型的二进制文件转换为文本。我们正在使用一个名为 pdftohtml 的简单实用程序(可通过自制软件获得)将我的 PDF 转换为人类可读的 HTML。您可以通过编辑您的 .git/config 文件为单个存储库设置此设置,或者通过编辑 ~ /.gitconfig 进行全局编辑

[diff "pdfconv"]
textconv=pdftohtml -stdout

然后,您需要做的就是将一个或多个文件模式与我们的 pdfconv 筛选器关联起来。您可以通过在存储库的根目录中创建 .gitattributes 文件来做到这一点。

*.pdf diff=pdfconv

配置完成后,git diff 将首先通过配置的转换器脚本运行二进制文件,然后对转换器输出进行比对。同样的技术可以用来从各种二进制文件中获得有用的比对,例如:zips、jar 和其他归档:使用 unzip-l(或类似文件)代替 pdf2html 将显示在提交图像之间添加或删除的路径:exiv2 可用于显示元数据变更,例如图像尺寸文档:存在用于将 .odf、.doc 和其他文档格式转换为纯文本的转换工具。必要时,字符串通常适用于不存在正式转换器的二进制文件。

比较文件:git diff 文件


可以向 git diff 命令传递明确的文件路径选项。文件路径传递给 git diff 时,比对操作的作用域将限定为指定文件。以下示例演示了这种用法。

git diff HEAD ./path/to/file

调用时,此示例的作用域为 ./path/to/file,它会将工作目录中的具体变更与索引进行比较,显示尚未暂存的变更。默认情况下,git diff 将执行与 HEAD 的比较。在上面的 git diff ./path/to/file 示例中省略了 HEAD 具有同样的效果。

git diff --cached ./path/to/file

使用 --cached 选项调用 git diff 时,比对会将暂存的变更与本地存储库进行比较。--cached 选项与 --staged 同义。

比较所有变更


在没有文件路径的情况下调用 git diff 将比较整个存储库中的变更。以上是文件特定的示例,可以在没有的情况下调用 ./path/to/file 参数,并且在本地代码存储库中的所有文件中具有相同的输出结果。

自上次提交以来的变更


默认情况下,git diff 会显示自上次提交以来所有未提交的变更。

git diff

比较两个不同提交之间的文件


git diff 可以将 Git 引用传递给提交进行比对。一些示例引用包括 HEAD、标记和分支名称。Git 中的每个提交都有一个提交 ID,您可以在执行 GIT LOG 时获得这个提交 ID。您也可以将这个提交 ID 传递给 git diff

git log --pretty=oneline
957fbc92b123030c389bf8b4b874522bdf2db72c add feature
ce489262a1ee34340440e55a0b99ea6918e19e7a rename some classes
6b539f280d8b0ec4874671bae9c6bed80b788006 refactor some code for feature
646e7863348a427e1ed9163a9a96fa759112f102 add some copy to body

$:> git diff 957fbc92b123030c389bf8b4b874522bdf2db72c ce489262a1ee34340440e55a0b99ea6918e19e7a

比较分支


比较两个分支

像所有其他引用输入一样将分支与 git diff 进行比较

git diff branch1..other-feature-branch

此示例引入了点运算符。此示例中的两个点表示比对输入是两个分支的尖端。如果省略点并在分支之间使用空格,也会产生同样的效果。此外,还有一个三点运算符:

git diff branch1...other-feature-branch

三点运算符通过变更第一个输入参数 branch1 来启动比对。它将 branch1 变更为两个比对输入之间共享的共同祖先提交引用,即 branch1 和其他功能分支的共享祖先。最后一个参数输入参数保持不变,就像其他功能分支的尖端一样。

比较来自两个分支的文件


要跨分支比较特定文件,请将该文件的路径作为第三个参数传递给 git diff

git diff main new_branch ./diff_test.txt

摘要


本页讨论了 Git 比对流程和 git diff 命令。我们讨论了如何读取 git diff 输出以及输出中包含的各种数据。提供了有关如何通过突出显示和颜色更改 git diff 输出的示例。我们讨论了不同的比对策略,例如如何比对分支中的文件和特定的提交。除了 git diff 命令外,我们还使用了 git loggit checkout


分享此文章
下一主题

推荐阅读

将这些资源加入书签,以了解 DevOps 团队的类型,或获取 Atlassian 关于 DevOps 的持续更新。

人们通过满是工具的墙进行协作

Bitbucket 博客

Devops 示意图

DevOps 学习路径

与 Atlassian 专家一起进行 Den 功能演示

Bitbucket Cloud 与 Atlassian Open DevOps 如何协同工作

注册以获取我们的 DevOps 新闻资讯

Thank you for signing up