设置和配置
获取和创建项目
基本快照
分支和合并
共享和更新项目
检查和比较
补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.44.1 → 2.49.0 没有更改
-
2.44.0
2024-02-23
- 2.43.1 → 2.43.6 没有更改
-
2.43.0
2023-11-20
- 2.32.1 → 2.42.4 没有更改
-
2.32.0
2021-06-06
- 2.31.1 → 2.31.8 没有更改
-
2.31.0
2021-03-15
- 2.21.1 → 2.30.9 没有更改
-
2.21.0
2019-02-24
- 2.13.7 → 2.20.5 没有更改
-
2.12.5
2017-09-22
- 2.10.5 → 2.11.4 没有更改
-
2.9.5
2017-07-30
- 2.5.6 → 2.8.6 没有更改
-
2.4.12
2017-05-05
- 2.1.4 → 2.3.10 没有更改
-
2.0.5
2014-12-17
描述
diff 命令 git diff-index, git diff-files, 和 git diff-tree 可以被告知以非常规的方式处理它们发现的差异,然后再显示 diff 输出。 这种操作统称为“diffcore 转换”。 这个简短的注释描述了它们是什么,以及如何使用它们来生成比传统类型更容易理解的 diff 输出。
操作链
git diff-* 系列的工作方式是首先比较两组文件
-
git diff-index 比较“tree”对象的内容和工作目录(当未使用
--cached
标志时)或“tree”对象和索引文件(当使用--cached
标志时); -
git diff-files 比较索引文件的内容和工作目录;
-
git diff-tree 比较两个“tree”对象的内容;
在所有这些情况下,命令本身首先可以选择性地通过在其命令行上给出的任何路径规范来限制两组文件,并比较两个结果文件集中的相应路径。
路径规范用于限制 diff 操作的范围。 它们删除指定路径名集之外的文件对。 例如,如果输入的文件对集包括
:100644 100644 bcd1234... 0123456... M junkfile
但是命令调用是 git diff-files myfile
,那么 junkfile 条目将从列表中删除,因为只考虑“myfile”。
比较的结果以类似于未使用 -p 选项时输出的格式从这些命令传递到内部称为“diffcore”的内容。 例如
in-place edit :100644 100644 bcd1234... 0123456... M file0 create :000000 100644 0000000... 1234567... A file4 delete :100644 000000 1234567... 0000000... D file5 unmerged :000000 000000 0000000... 0000000... U file6
diffcore 机制被馈送一个此类比较结果的列表(每个比较结果都被称为“文件对”,尽管此时它们中的每一个都讨论一个单独的文件),并将这样的列表转换为另一个列表。 目前有 5 种这样的转换
-
diffcore-break
-
diffcore-rename
-
diffcore-merge-broken
-
diffcore-pickaxe
-
diffcore-order
-
diffcore-rotate
这些按顺序应用。 git diff-* 命令找到的文件对集被用作 diffcore-break 的输入,diffcore-break 的输出被用作下一个转换的输入。 然后,最终结果传递给输出例程,并生成 diff-raw 格式(请参阅 git diff-* 命令的手册的输出格式部分)或 diff-patch 格式。
diffcore-break:用于拆分完全重写
链中的第二个转换是 diffcore-break,它由 git diff-* 命令的 -B 选项控制。 它用于检测表示“完全重写”的文件对,并将这样的文件对分成两个表示删除和创建的文件对。 例如,如果输入包含此文件对
:100644 100644 bcd1234... 0123456... M file0
如果它检测到文件 "file0" 被完全重写,它会将其更改为
:100644 000000 bcd1234... 0000000... D file0 :000000 100644 0000000... 0123456... A file0
为了拆分文件对的目的,diffcore-break 检查修改前后文件内容之间的变化程度(即,以上述示例中 SHA-1 内容 ID 为“bcd1234…”和“0123456…”的内容)。 原始内容的删除量和新材料的插入量加在一起,如果超过“break score”,则将文件对分成两个。 break score 默认为原始文件和结果文件中较小者大小的 50%(即,如果编辑缩小了文件,则使用结果的大小;如果编辑拉长了文件,则使用原始文件的大小),并且可以通过在 "-B" 选项后给出一个数字来自定义(例如,"-B75" 告诉它使用 75%)。
diffcore-rename:用于检测重命名和复制
此转换用于检测重命名和复制,由 git diff-* 命令的 -M 选项(用于检测重命名)和 -C 选项(用于检测复制)控制。 如果输入包含这些文件对
:100644 000000 0123456... 0000000... D fileX :000000 100644 0000000... 0123456... A file0
并且删除的文件 fileX 的内容与创建的文件 file0 的内容足够相似,那么重命名检测会合并这些文件对并创建
:100644 100644 0123456... 0123456... R100 fileX file0
当使用 "-C" 选项时,修改的文件和删除的文件(以及未修改的文件,如果使用了 "--find-copies-harder" 选项)的原始内容被认为是重命名/复制操作中源文件的候选者。 如果输入像这些文件对一样,讨论一个修改过的文件 fileY 和一个新创建的文件 file0
:100644 100644 0123456... 1234567... M fileY :000000 100644 0000000... bcd3456... A file0
比较 fileY 的原始内容和 file0 的结果内容,如果它们足够相似,则将它们更改为
:100644 100644 0123456... 1234567... M fileY :100644 100644 0123456... bcd3456... C100 fileY file0
在重命名和复制检测中,diffcore-break 中使用的相同“变化程度”算法用于确定两个文件是否“足够相似”,并且可以通过在 "-M" 或 "-C" 选项后给出一个数字来自定义为使用与默认值 50% 不同的相似度分数(例如,"-M8" 告诉它使用 8/10 = 80%)。
请注意,当重命名检测打开但复制和中断检测都关闭时,重命名检测会添加一个初步步骤,首先检查文件是否在目录之间移动,同时保持其文件名不变。 如果添加到目录中的文件的内容与从不同目录中删除的同名文件足够相似,则会将它们标记为重命名,并将它们排除在稍后的二次步骤之外(即成对比较所有未匹配的文件以找到“最佳”匹配,由最高内容相似度确定)。 因此,例如,如果删除的 docs/ext.txt 和添加的 docs/config/ext.txt 足够相似,它们将被标记为重命名,并防止添加的 docs/ext.md 可能与删除的 docs/ext.txt 更相似,从而被视为稍后步骤中的重命名目标。 因此,初步的“匹配相同文件名”步骤使用略高的阈值来将文件对标记为重命名,并停止考虑其他候选对象以获得更好的匹配。 在此初步传递中,每个文件最多完成一次比较;因此,如果精确重命名检测后在整个目录层次结构中存在多个剩余的 ext.txt 文件,则可能会跳过这些文件的此初步步骤。
注意。 当 "-C" 选项与 --find-copies-harder
选项一起使用时,git diff-* 命令会将未修改的文件对以及修改的文件对馈送到 diffcore 机制。 这使复制检测器能够将未修改的文件视为复制源候选者,但代价是速度变慢。 如果没有 --find-copies-harder
,只有在复制的文件恰好在同一变更集中被修改过的情况下,git diff-* 命令才能检测到复制。
diffcore-merge-broken:用于将完全重写重新组合在一起
此转换用于将 diffcore-break 中断的文件对,并且没有被 diffcore-rename 转换为重命名/复制的文件对,重新合并为单个修改。 当使用 diffcore-break 时,这始终运行。
为了将被打断的文件对合并回去,它使用了与 diffcore-break 和 diffcore-rename 不同的“变更范围”计算方法。它仅计算原始文件的删除量,而不计算插入量。 如果你从一个 100 行的文档中删除了 10 行,即使你添加了 910 行新行来创建一个 1000 行的新文档,你也没有进行完全的重写。 diffcore-break 会将这种情况打断,以便帮助 diffcore-rename 将这样的文件对视为重命名/复制检测的候选对象,但是如果以这种方式打断的文件对没有与其他文件对匹配以创建重命名/复制,那么此转换会将它们合并回原始的“修改”。
可以使用 -B 选项的第二个数字来调整“变更范围”参数,默认值为 80%(也就是说,除非原始材料的删除量超过 80%,否则被打断的文件对将被合并回单个修改),例如:
-
-B50/60(给 diffcore-break 50% 的“打断分数”,diffcore-merge-broken 使用 60%)。
-
-B/60(与上面相同,因为 diffcore-break 默认为 50%)。
请注意,早期的实现将打断的文件对作为单独的创建和删除补丁留下。 这是一个不必要的hack,最新的实现始终将所有被打断的文件对合并回修改,但是生成的补丁输出格式不同,以便在进行完全重写时更容易审查,它会显示旧版本的全部内容,并以 - 为前缀,然后显示新版本的全部内容,并以 + 为前缀。
diffcore-pickaxe:用于检测指定字符串的添加/删除
此转换将文件对的集合限制为那些以某种方式在 preimage 和 postimage 之间更改指定字符串的文件对。 -S<block-of-text> 和 -G<regular-expression> 选项用于指定搜索这些字符串的不同方式。
"-S<block-of-text>" 检测 preimage 和 postimage 中指定文本块出现次数不同的文件对。 按照定义,它不会检测文件内的移动。 此外,当一个 changeset 在不影响感兴趣的字符串的情况下整体移动文件时,diffcore-rename 会像往常一样启动,并且 -S
会忽略该文件对(因为该字符串的出现次数在该重命名检测到的文件对中没有改变)。 与 --pickaxe-regex
一起使用时,将 <block-of-text> 视为扩展的 POSIX 正则表达式来进行匹配,而不是字面字符串。
"-G<regular-expression>"(助记符:grep)检测文本差异具有与给定正则表达式匹配的已添加或已删除行的文件对。 这意味着它将检测文件内的移动(或重命名检测认为的相同文件),这会产生噪声。 该实现运行 diff 两次并 greps,这可能会非常耗时。 为了加快速度,将忽略没有 textconv 过滤器的二进制文件。
当在没有 --pickaxe-all
的情况下使用 -S
或 -G
时,只有符合各自标准的文件对才会保留在输出中。 当使用 --pickaxe-all
时,如果即使只有一个文件对在一个 changeset 中符合各自的标准,则会保留整个 changeset。 此行为旨在使审查整个 changeset 上下文中的更改更容易。
diffcore-order:用于基于文件名对输出进行排序
用于根据用户(或项目)的喜好重新排序文件对,并由 git diff-* 命令的 -O 选项控制。
这需要一个文本文件,其每一行都是一个 shell glob 模式。 在文件中较早行上与 glob 模式匹配的文件对的输出在与较晚行匹配的文件对之前输出,并且不与任何 glob 模式匹配的文件对最后输出。
例如,核心 Git 的典型 orderfile 可能如下所示
README Makefile Documentation *.h *.c t
diffcore-rotate:用于更改输出开始的路径
此转换采用一个路径名,并旋转文件对集合,以便给定路径名的文件对首先出现,可以选择丢弃其之前的路径。 这用于实现 --skip-to
和 --rotate-to
选项。 当指定的路径名不在文件对集合中时,会发生错误,但与“git log”系列命令一起使用时,出错是没有用的,因为期望给定的路径会被“git log”命令显示的每个提交修改是不合理的。 因此,当与“git log”一起使用时,与给定路径名排序相同的文件对或在其之后排序的第一个文件对是输出开始的位置。
此转换与 diffcore-order 结合使用将产生意外结果,因为当 diffcore-order 生效时,此转换的输入可能未排序。
GIT
属于 git[1] 套件的一部分