让 git diff --stat 显示完整的文件路径
Posted
技术标签:
【中文标题】让 git diff --stat 显示完整的文件路径【英文标题】:Making git diff --stat show full file path 【发布时间】:2012-05-14 14:53:35 【问题描述】:在执行git diff --stat
时,一些文件列出了来自存储库库的完整路径,但一些文件列出为:
.../short/path/to/filename.
即路径以...
开头,只显示短路径。
我希望git diff
列出所有文件的完整文件路径,以便脚本轻松处理它。有什么方法可以让git diff
始终显示完整路径
【问题讨论】:
【参考方案1】:默认情况下,git diff
会截断其输出以适应 80 列终端。
您可以通过使用--stat
option 指定值来覆盖它:
--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
,因为它更像是一个“管道”命令,尽管我怀疑你会很好。请注意,使用时你需要与--stat
相同的额外文本git diff-tree
. 使用git diff
“porcelain”前端和git diff-tree
管道命令之间的本质区别在于git diff
查找您配置的设置以查找diff.renames
等选项以决定是否进行重命名检测. 好吧,加上前端git diff
将相当于git diff-index
,例如,如果您将提交与索引进行比较。换句话说,git diff
读取您的配置 并且自动调用正确的管道。)
【讨论】:
git diff --numstat 和 diff-tree 一样 请注意,要限制最后一部分的宽度 (+++/---),您可以使用单独的--stat-graph-width=...
开关。另请注意,将--stat-graph-width=
和--stat-name-width=
设置得高是不够的,您还必须将--stat-width=
设置得足够大以覆盖两者。
@jakub.g:好点。基于对 git 源代码的一些挖掘,这与 git 1.7.10 一起使用。
有没有办法全球化?每次都打字太疯狂了。
@Rudie:唉,不:有一个配置变量 diff.statGraphWidth
可以用来设置 --stat-graph-width
值,但其他默认为您的终端宽度。 (所以,替代答案:“是的,只需将您的终端窗口设为 1000 列宽”:-))【参考方案2】:
对于脚本处理,最好使用以下方法之一:
# 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
选项结合使用时,这些都变得更便于进行健壮的脚本处理。
【讨论】:
根据我的测试,您不会使用这些命令收到资源的完整路径。现在我只看到已删除文件的相对路径。不知道是不是只有这些文件才有这种情况。 所有输出都将返回相对于git rev-parse --show-toplevel
的路径。最初的问题是指截断的路径,这是 diffstats 中的一个问题,特别是对于长文件名或 --stat-name-width
的低值。上面的命令不会截断路径,但会根据请求显示“完整”路径,尽管它仍然相对于存储库根目录。【参考方案3】:
对于 Bash 用户,您可以使用 $COLUMNS
变量来自动填充可用的终端宽度:
git diff --stat=$COLUMNS
很长的路径名可能仍会被截断;在这种情况下,您可以使用 --stat-graph-width
减小 +++/--- 部分的宽度,例如这会将其限制为终端宽度的 1/5:
git show --stat=$COLUMNS --stat-graph-width=$(($COLUMNS/5))
对于更通用的解决方案,您可以使用tput cols
的输出来确定终端宽度。
【讨论】:
有没有办法全球化--stat=$COLUMNS,$COLUMNS
?每次都打字太疯狂了。
@Rudie 将export COLUMNS
添加到您的~/.bashrc
,并在您的~/.gitconfig
中的[alias]
下添加smart-diff = ! "gitsmartdiff() git diff $2 --stat=$COLUMNS,$COLUMNS; ; gitsmartdiff"
@user151841 这只会改变diff
。我希望它也适用于合并和拉取等。 (甚至不能在那里手动完成。)我认为 GIT 不支持它。
@Rudie 好吧,在拉取或合并完成后,您可以区分以前的哈希值和新的哈希值。
@user151841 当然可以,但是合并已经给出了统计摘要。没有参数/配置。如果所有“统计摘要”都使用相同的配置,那就太好了。【参考方案4】:
有一个选项--name-only
:git diff --name-only
。其他 git 命令也支持该选项,例如 show
和 stash
。
该选项不会缩短路径。
【讨论】:
git diff-tree
也有相应的选项,但您还需要指定其他选项,例如 git diff-tree --name-only -r --no-commit-id HEAD
。请参阅我的回答 ***.com/a/67330880/1507124 了解更多信息【参考方案5】:
我发现一个简单的解决方案是这样做:(仅适用于 *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)/"
【讨论】:
我发现仅仅使用--relative
对我帮助很大。 (我已经使用了--stat
宽度选项。【参考方案6】:
我创建了以下 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(-)
【讨论】:
【参考方案7】:git diff
是一个瓷器(用户友好)命令。出于脚本目的,您可能希望使用相应的管道命令git diff-tree
。
您可以使用--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 对象的 blob。
提交是一个treeish
对象,它指向存储库根目录中的对象。目录也是treeish
对象,而文件是blobs
。
运行git diff-tree HEAD
将比较HEAD
和HEAD~1
的blob,并包含存储库根的blob 差异。要查看所有不在根目录中的已更改文件,我们需要进入目录treeish
对象。这是使用-r
(如递归)选项实现的。
请注意,这允许在任意提交中一二比较任意目录。
默认情况下,如果只指定了一个 commit 对象,则会将其与其父对象进行比较。即,运行git diff-tree HEAD
等价于git diff-tree HEAD HEAD~1
。如果您仅将一个提交指定为 treeish 对象,则会显示父提交 ID。使用--no-commit-id
可以解决这个问题。
git-diff-tree
打印出很多我们不想要的信息(id、权限、是否是添加、删除、修改)。我们只想要名字,所以我们使用--name-only
。
如果我们想要绝对路径,我们需要使用类似git rev-parse --show-toplevel
之类的东西为所有行添加前缀。这将获取存储库的绝对路径,没有尾随 /
。所以我们添加了它。
--line-prefix=`git rev-parse --show-toplevel`/
【讨论】:
【参考方案8】:我发现 diff --stat 的行为在 git 1.7.10 附近发生了变化,以前它默认将文件路径缩短到固定宽度 - 现在它显示的内容与终端窗口允许的一样多。如果您遇到此问题,请确保升级到 1.8.0 或更高版本。
【讨论】:
以上是关于让 git diff --stat 显示完整的文件路径的主要内容,如果未能解决你的问题,请参考以下文章