如何判断 git 中是否有任何工作副本更改

如何判断 git 中是否有任何工作副本更改

我使用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 statusgit 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
}

相关内容