使 git diff --stat 显示完整的文件路径



在执行git diff --stat时,某些文件以存储库库的完整路径列出,但有些文件列为:

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

也就是说,路径以...开头,仅显示短路径。

我想git diff列出所有文件的完整文件路径,以便脚本轻松处理。有没有办法让我git diff始终显示完整的路径

默认情况下,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读取您的配置自动调用正确的管道

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

# 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 选项结合使用时,这些选项对于强大的脚本处理变得更加方便。

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

git diff --stat=$COLUMNS

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

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

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

有一个

选项--name-onlygit diff --name-only 。其他 git 命令(如 showstash (也支持该选项。

该选项不会缩短路径。

我发现一个简单的解决方案是这样做:(仅适用于 *nix,抱歉没有 osx(

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

这个版本适用于两者,但在osx上看起来并不好。

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

git diff是一个瓷器(用户友好(命令。出于脚本编写目的,您可能希望使用相应的管道命令git diff-tree

您可以让git diff-tree使用--name-only-r--no-commit-id选项的组合来输出相对于 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的 blob,并包含存储库根目录的 blob 差异。要查看不在根目录中的所有已更改文件,我们需要下降到目录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`/

我创建了以下 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(-)

我发现 diff --stat 的行为在 git 1.7.10 左右发生了变化,以前它会默认将文件路径缩短为固定宽度 - 它现在显示的尽可能多的终端窗口允许。如果遇到此问题,请确保升级到 1.8.0 或更高版本。

最新更新