设置 git diff —— stat 显示完整的文件路径

在执行 git diff --stat时,一些文件列出了来自存储库基础的完整路径,但是一些文件列出如下:

.../short/path/to/filename.

即路径以 ...开始,并且只显示短路径。

我希望 git diff列出所有文件的完整文件路径,以便脚本轻松处理。有没有什么办法可以让 git diff总是显示完整的路径

43345 次浏览

默认情况下,git diff截断其输出以适应80列的终端。

您可以通过使用 --stat选项指定值来覆盖它:

--stat[=<width>[,<name-width>[,<count>]]]
Generate a diffstat. You can override the default output width for
80-column terminal by --stat=<width>. The width of the filename
part can be controlled by giving another width to it separated by a
comma. By giving a third parameter <count>, you can limit the
output to the first <count> lines, followed by ...  if there are
more.


These parameters can also be set individually with
--stat-width=<width>, --stat-name-width=<name-width> and
--stat-count=<count>.

例如,通过将输出值设置为一个非常大的数字:

git diff --stat=10000

注意,产生了相对于 git 存储库根目录的路径。

(对于脚本,您可能希望直接使用 git diff-tree,因为它更像是一个“管道”命令,尽管我怀疑无论哪种方式都可以。注意,在使用 git diff-tree时,需要使用与 --stat相同的额外文本。使用 git diff“瓷器”前端与使用 git diff-tree管道命令之间的本质区别在于,git diff查找 diff.renames等选项的配置设置,以决定是否进行重命名检测。例如,如果您将提交与索引进行比较,那么加上前端 git diff将执行相当于 git diff-index的操作。换句话说,就是 git diff--stat0和 --stat1。)

我发现 diff-stat 的行为在 git1.7.10左右发生了变化,之前它默认会将文件路径缩短到一个固定的宽度——现在它会在终端窗口允许的范围内显示。如果遇到此问题,请确保升级到1.8.0或更高版本。

对于 Bash 用户,可以使用 $COLUMNS变量自动填充可用的终端宽度:

git diff --stat=$COLUMNS

非常长的路径名可能仍然会被截断; 在这种情况下,您可以使用 --stat-graph-width减少 + + +/——部分的宽度,例如,这将其限制为终端宽度的1/5:

git show --stat=$COLUMNS --stat-graph-width=$(($COLUMNS/5))

对于更通用的解决方案,可以使用 tput cols的输出来确定终端宽度。

对于脚本处理,最好使用下列方法之一:

# list just the file names
git diff --name-only
path/to/modified/file
path/to/renamed/file




# list the names and change statuses:
git diff --name-status
M       path/to/modified/file
R100    path/to/existing/file   path/to/renamed/file




# list a diffstat-like output (+ed lines, -ed lines, file name):
git diff --numstat
1       0       path/to/modified/file
0       0       path/to/{existing => renamed}/file

当与使用 NUL作为字段终止符的 -z选项结合使用时,这些选项对于健壮的脚本处理都会更加方便。

有一个选项 --name-only: git diff --name-only。该选项也支持其他 git 命令,如 showstash

选项不会缩短路径。

我创建了以下 git 别名:

diffstat = ! "gitdiffstat() {  git diff --stat=$(tput cols) ${1:-master} ; }; gitdiffstat"

它从 tput cols命令读取列计数。它默认不同于 master,但是您可以选择指定另一个分支。

$ git diffstat
.gitalias | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

我找到的一个简单的解决方案是这样做: (只能在 * nix 上工作,对不起,没有 osx)

git diff --stat=$COLUMNS --relative | head -n -1 | cut -c 2- | xargs -d '\n' -P4 printf "$(pwd)/%s\n"

这个版本对两者都适用,但是在 osx 上看起来不太好。

git diff --stat=$COLUMNS --relative | sed -e '$ d' | cut -c 2- | xargs -n4 -I{} echo "$(pwd)/{}"

git diff是一个简单的(用户友好的)命令。

您可以使用 --name-only-r--no-commit-id选项的组合,让 git diff-tree输出相对于 git 存储库的完整路径。

例子

在当前分支的“最后一次”(HEAD)提交中更改的文件路径。

git diff-tree --name-only -r --no-commit-id HEAD

main分支上最后一次提交中的文件路径

git diff-tree --name-only -r --no-commit-id main

main分支上提交的最后三个文件的路径

git diff-tree --name-only -r main main~3

路径 src/下最后一次提交的文件的路径

git diff-tree --name-only -r --no-commit-id main src/

在当前分支上的最后一次提交中更改的文件的绝对路径

git diff-tree --name-only -r --no-commit-id --line-prefix=`git rev-parse --show-toplevel`/ HEAD

解释

git diff-tree比较两个 对象的 一团团

提交是一个 treeish对象,它指向存储库根中的对象。目录也是 treeish对象,而文件是 blobs

运行 git diff-tree HEAD将比较 HEADHEAD~1的 blobs,并包含存储库根的 blobs 的差异。要查看不在根目录中的所有更改过的文件,我们需要下降到目录 treeish对象中。这是通过使用 -r(如递归)选项实现的。

注意,这允许在任意提交中有两个比较任意目录。

默认情况下,如果只指定了一个 承诺对象,则将其与其父对象进行比较。也就是说,运行 git diff-tree HEAD相当于 git diff-tree HEAD HEAD~1。如果只指定一个提交作为 对象,则显示父提交 id。使用 --no-commit-id可以消除这个问题。

git-diff-tree打印了很多我们不想要的信息(id、权限,无论是添加、删除还是修改)。我们只需要名称,所以我们使用 --name-only

如果我们想要绝对路径,我们需要使用类似于 git rev-parse --show-toplevel的东西给所有行前缀。这将获取存储库的绝对路径,而不带有后面的 /。所以我们加上这个。

--line-prefix=`git rev-parse --show-toplevel`/