我使用git diff --exit-code
颜色来显示我的 shell 提示符,这样我就能知道工作副本中是否存在差异。在非常大的存储库中,如果git diff
不使用额外的参数,这会花费很长时间。
我曾希望这--exit-code
会导致 git 在发现第一个差异后立即退出,但事实上,它实际上会打印差异。当使用 运行时--quiet
,它当然不会打印差异,但仍然需要同样长的时间,这表明它仍在计算所有更改,即使没有显示它们。
所以我的问题是:有没有办法git diff
(或任何其他 git 命令)简单地检查是否存在是任何差异,并相应地设置退出代码,但不必费心查找和格式化所有实际更改?
编辑:关于 repo 的大小,它大约有 7.5G(其中 4.1G 是.git/
目录),并且有 ~160k 个跟踪文件。
答案1
据我所知,没有任何方法可以直接用 git 来做到这一点。
但是,您可以使用以下 shell 脚本片段来更快速地进行检查:
#!/bin/sh
[ `git status --porcelain=1 | wc -l` -ne 0 ] && exit 1
其作用是从命令中获取机器可解析的输出git status
(git diff
由于它只检查是否存在更改,而不是更改是什么,因此运行速度比在大型存储库上更快),计算行数(格式--porcelain=1
将为每个修改的文件返回一行,如果没有修改,则不返回任何行),然后如果数字非零,则以非零退出状态退出。
您还可以直接将其嵌入到生成提示的任何脚本中,通过拉出条件表达式(中的位[]
)并在任何 if 语句中使用它来检查当前的退出代码git diff --quiet
。
答案2
我无法立即找到一个简单的命令,但我确实检查了 oh-my-zsh 中的 git prompt 模块的作用,而且它相当快:
检查 的输出git status --porcelain --untracked-files=no
。当文件被修改时,M
第二列会显示 ,而当存在文件冲突时,U
第一列会显示 。
你可以做这样的事情:
prompt() {
git status --porcelain --untracked-files=no | grep '^.M' > /dev/null
CHANGED=$?
# $CHANGED -eq 0 when there are uncommitted changes
git status --porcelain --untracked-files=no | grep '^U.' > /dev/null
CONFLICTS=$?
# $CONFLICTS -eq 0 when there are merge or rebase conflicts
git status --porcelain --untracked-files=no | grep '^' > /dev/null
CLEAN=$((1 - $?))
# $CLEAN -eq 0 when there are *no* changes, conflicts, or uncommitted staged files
}