directory search
Guides gitattributes giteveryday gitglossary gitignore gitmodules gitrevisions gittutorial gitworkflows Administration git archive git bundle git clean git filter-branch git fsck git gc git instaweb git reflog Basic Snapshotting git add git commit git diff git mv git reset git rm git status Branching and Merging git branch git checkout git log git merge git mergetool git stash git tag Debugging git bisect git blame git grep Email git am git format-patch git request-pull git send-email External Systems git fast-import git svn Getting and Creating Projects git clone git init Git git annotate git archimport git bisect-lk2009 git check-attr git check-mailmap git check-ref-format git checkout-index git cherry git citool git column git credential git credential-cache git credential-store git cvsexportcommit git cvsimport git cvsserver git diff-files git diff-tree git difftool git fast-export git fetch-pack git fmt-merge-msg git get-tar-commit-id git gui git http-backend git http-fetch git http-push git imap-send git index-pack git interpret-trailers git ls-remote git ls-tree git mailinfo git mailsplit git merge-file git merge-index git merge-one-file git merge-tree git mktag git mktree git name-rev git notes git p4 git pack-objects git pack-redundant git pack-refs git parse-remote git patch-id git prune git prune-packed git quiltimport git receive-pack git remote-ext git remote-fd git remote-testgit git repack git replace git rerere git send-pack git sh-i18n git sh-setup git shell git show-branch git show-index git stripspace git unpack-file git unpack-objects git upload-archive git upload-pack git var git verify-commit git verify-tag git whatchanged git worktree Inspection and Comparison git describe git shortlog git show Miscellaneous api credentials api index gitcli gitcore tutorial gitcredentials gitcvs migration gitdiffcore githooks gitk gitnamespaces gitremote helpers gitrepository layout gitsubmodules gittutorial 2 gitweb gitweb.conf pack format User Manual Patching git apply git cherry-pick git rebase git revert Plumbing Commands git cat-file git check-ignore git commit-tree git count-objects git diff-index git for-each-ref git hash-object git ls-files git merge-base git read-tree git rev-list git rev-parse git show-ref git symbolic-ref git update-index git update-ref git verify-pack git write-tree Server Admin git daemon git update-server-info Setup and Config git git config git help Sharing and Updating Projects git fetch git pull git push git remote git submodule
characters

名称

gitdiffcore - Tweaking diff output

概要

git diff *

描述

该DIFF命令git diff-indexgit diff-files以及git diff-tree可以告诉操作展示之前,他们在非传统的方式找到差异diff的输出。操作统称为“diffcore转换”。本短文描述了它们是什么以及如何使用它们来产生diff比传统类型更容易理解的输出。

操作链

git diff-*系列的工作原理是:第一比较两组文件:

  • git diff-index比较“树”对象和工作目录(当--cached不使用标志时)或“树”对象和索引文件(使用--cached标志时)的内容;

  • git diff-files 比较索引文件和工作目录的内容;

  • git diff-tree 比较两个“树”对象的内容;

在所有这些情况下,命令本身首先可选地通过在它们的命令行上给出的任何路径规格限制两组文件,并比较两组得到的文件中的对应路径。

pathspecs用于限制差异操作的世界。他们删除指定的路径名集外的文件对。例如,如果文件对的输入集包括:

:100644 100644 bcd1234... 0123456... M junkfile

但是命令调用是git diff-files myfile,那么junkfile条目将从列表中删除,因为只考虑“myfile”。

比较结果从这些命令传递到内部称为“diffcore”的内容,格式类似于不使用-p选项时输出的格式。例如

in-place edit  :100644 100644 bcd1234... 0123456... M file0
create         :000000 100644 0000000... 1234567... A file4delete         :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

这些按顺序应用。filepairs 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检查修改之前和之后文件内容之间的变化程度(即具有“bcd1234 ...”和“0123456 ...”作为其SHA-1内容ID的内容在上面的例子中)。原始内容的删除量和新素材的插入量相加在一起,如果超过“中断分数”,则文件对被分成两部分。中断分数默认为原始大小和结果大小的50%(即,如果编辑缩小文件,则使用结果的大小;如果编辑延长文件,则使用原始大小),并且可以通过在“-B”选项之后给出一个数字来进行定制(例如“-B75”告诉它使用75%)。

Diffcore-rename:用于检测重命名和复制

此转换用于检测重命名和副本,并由-M选项(以检测重命名)和-C选项(以检测副本)控制git diff-*命令。如果输入包含这些文件对象:

: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中使用的相同“变化程度”算法用于确定两个文件是否“足够相似”,并且可以定制为使用与默认值50%相似的得分在“-M”或“-C”选项之后给出一个数字(例如“-M8”来告诉它使用8/10 = 80%)。

注意。当“-C”选项与--find-copies-harder选项一起使用时,git diff-*命令将未修改的文件对提供给diffcore机制以及修改的机制。这可以让复制检测器将未修改的文件视为复制源候选项,代价是速度较慢。如果没有--find-copies-hardergit diff-*只有当被复制的文件在相同的变更集中被修改时,命令才能检测到拷贝。

Diffcore-merge-broken:将完整的重写放在一起

此转换用于合并由diffcore-break打破的文件对,而不是通过diffcore-rename转换为rename/copy,返回到单个修改中。当使用diffcore-break时,它总是运行。

为了合并破损的文件对,它使用了diffcore-break和diffcore-rename使用的不同的“变化范围”计算。它只计算从原始的删除,并不计入插入。如果您从100行文档中只删除了10行,即使您添加了910行来创建新的1000行文档,也没有执行完全重写。diffcore-break打破了这种情况,以帮助diffcore-rename将文件对视为rename/copy检测的候选对象,但是如果文件对以这种方式打破与其他文件对不匹配以创建rename/copy,则该转换将它们合并回来进入原来的“修改”。

“extent of changes”参数可以从默认的80%调整(也就是说,除非超过80%的原始材料被删除,破碎的对会重新合并为一个修改),给第二个数字为-B选项,如下所示:

  • -B50/60(给予50%的“破裂得分”以弥补破裂,使用60%作为diffcore-merge-broken)。

  • -B/60(与上面相同,因为diffcore-break默认为50%)。

请注意,早期的实现会将一对损坏的对作为单独的创建和删除补丁程序。这是一种不必要的破解,最新的实现总是将所有破损的对重新合并到修改中,但是由此产生的修补程序输出格式不同,以便在完全重写的情况下更容易查看,方法是显示旧版本前缀的全部内容-,随后新版本的全部内容都以前缀+

Diffcore-pickaxe:用于检测指定字符串的addition/deletion

此转换将文件对的集合限制为那些以某种方式在预映像和postimage之间更改指定字符串的文件对。-S <文本块>和-G <正则表达式>选项用于指定查找这些字符串的不同方式。

“-S <block of text>”检测文件对象,其前像和后像具有不同的指定文本块的出现次数。根据定义,它不会检测文件中的移动。另外,当变更集移动批量文件而不影响有趣的字符串时,diffcore-rename像往常一样踢,并-S省略文件对(因为该字符串的出现次数在该重命名检测的文件对中没有变化)。使用时--pickaxe-regex,将<文本块>视为扩展的POSIX正则表达式进行匹配,而不是文字字符串。

“-G <regular expression>”(助记符:grep)检测文本对,其文本差异的添加行或删除行与给定正则表达式匹配。这意味着它会检测文件中(或重命名检测认为是同一个文件)的移动,这是噪声。该实现运行差异两次,greps,这可能是相当昂贵的。

如果使用-S-G不使用--pickaxe-all,则只有符合其各自标准的文件对保留在输出中。何时--pickaxe-all使用,如果即使一个文件对在变更集中与其各自的标准相匹配,整个变更集也会保留。此行为旨在使整个变更集环境中的审阅更容易。

Diffcore-order:用于根据文件名对输出进行排序

这用于根据用户(或项目)的口味重新排列文件对,并由git diff-*命令的-O选项控制。

这需要一个文本文件,每个文件的行都是一个shell glob模式。匹配文件中较早行的全局模式的文件对在比较后一行匹配之前输出,并且最后输出不匹配任何全局模式的文件对。

举个例子,核心Git的一个典型的命令文件可能看起来像这样:

README
Makefile
Documentation*.h*.c
t

也可以看看

git-diff[1], git-diff-files[1], git-diff-index[1], git-diff-tree[1], git-format-patch[1], git-log[1], gitglossary[7], The Git User’s Manual

Previous article: Next article: