通过脚本确定 Git 工作目录是否干净

通过脚本确定 Git 工作目录是否干净

rsync我有一个以 Git 工作目录作为目标运行的脚本。我希望脚本具有不同的行为,具体取决于工作目录是否干净(没有要提交的更改)。例如,如果输出git status如下,我希望脚本退出:

git status
Already up-to-date.
# On branch master
nothing to commit (working directory clean)
Everything up-to-date

如果目录不干净,那么我希望它执行更多命令。

如何在 shell 脚本中检查类似上面的输出?

答案1

解析 的输出git status是一个坏主意,因为输出是人类可读的,而不是机器可读的。无法保证输出在 Git 的未来版本或不同配置的环境中保持相同。

UVV评论git status是在正确的轨道上,但不幸的是,当有未提交的更改时,返回代码不会改变。然而,它确实提供了--porcelain选项,这会导致 的输出git status --porcelain被格式化为易于脚本解析的格式,无论用户配置如何,跨 Git 版本都将保持稳定。

我们可以使用 的空输出git status --porcelain作为没有要提交的更改的指示器:

if [ -z "$(git status --porcelain)" ]; then 
  # Working directory clean
else 
  # Uncommitted changes
fi

如果我们不关心工作目录中未跟踪的文件,我们可以使用--untracked-files=no可以选择忽略这些:

if [ -z "$(git status --untracked-files=no --porcelain)" ]; then 
  # Working directory clean excluding untracked files
else 
  # Uncommitted changes in tracked files
fi

为了使其在以下条件下更加稳健实际上导致git status失败而没有输出到stdout,我们可以将检查细化为:

if output=$(git status --porcelain) && [ -z "$output" ]; then
  # Working directory clean
else 
  # Uncommitted changes
fi

还值得注意的是,虽然git status当工作目录不干净时不会给出有意义的退出代码,但git diff提供了--exit-code选项,这使得它的行为类似于差异实用程序,即1当存在差异且未0发现差异时以状态退出。

使用它,我们可以通过以下方式检查未暂存的更改:

git diff --exit-code

并进行了但未提交的更改:

git diff --cached --exit-code

虽然git diff可以通过适当的参数报告子模块中未跟踪的文件--ignore-submodules,不幸的是,似乎没有办法让它报告实际工作目录中未跟踪的文件。如果工作目录中未跟踪的文件是相关的,git status --porcelain这可能是最好的选择。

答案2

使用:

git update-index --really-refresh
git diff-index --quiet HEAD

返回代码反映了工作目录的状态(0 = 干净,1 = 脏)。未跟踪的文件将被忽略。

答案3

小幅扩展至安德烈的出色的回答

未跟踪的文件将被忽略。

git update-index --really-refresh
if git diff-index --quiet HEAD
then
  GIT_MODS="clean"
else
  GIT_MODS="dirty"
fi

如果你想避免在 stdout 中放入东西,你可能需要添加>> /dev/null或类似的就update-index行了。

答案4

我做了这样的测试

TEST=$(git status --porcelain|wc -l)
if [ 0 -eq $TEST ]; then
   echo "No changes"
else
   echo "Changes"
fi 

相关内容