如何检查是否有's没有被提交在当前分支?

目标是获得可以在shell命令中计算的明确状态。

我尝试了git status,但它总是返回0,即使有项目提交。

git status
echo $?  #this is always 0

我有一个主意,但我认为这是一个相当糟糕的主意。

if [ git status | grep -i -c "[a-z]"> 2 ];
then
code for change...
else
code for nothing change...
fi

还有别的办法吗?


更新以下解决方案,请参阅Mark Longair的帖子

我试过了,但它引起了一个问题。

if [ -z $(git status --porcelain) ];
then
echo "IT IS CLEAN"
else
echo "PLEASE COMMIT YOUR CHANGE FIRST!!!"
echo git status
fi

我得到以下错误[: ??: binary operator expected

现在,我看着这个人,试着改变一下。

=================== 我希望代码,希望更好的答案 ======================

#if [ `git status | grep -i -c "$"` -lt 3 ];
# change to below code,although the above code is simple, but I think it is not strict logical
if [ `git diff --cached --exit-code HEAD^ > /dev/null && (git ls-files --other --exclude-standard --directory | grep -c -v '/$')` ];
then
echo "PLEASE COMMIT YOUR CHANGE FIRST!!!"
exit 1


else
exit 0
fi
102143 次浏览

git status的返回值只是告诉你git status的退出码,而不是是否有任何修改要提交。

如果你想要一个更计算机可读的git status输出版本,请尝试

git status --porcelain

有关这方面的更多信息,请参阅git status的描述。

示例使用(脚本简单地测试git status --porcelain是否给出任何输出,不需要解析):

if [ -n "$(git status --porcelain)" ]; then
echo "there are changes";
else
echo "no changes";
fi

请注意,你必须对测试的字符串加引号,即git status --porcelain的输出。有关测试结构的更多提示,请参阅高级Bash脚本编写指南 (Section 字符串比较)。

测试git status --porcelain的输出是否为空的另一种方法是分别测试你关心的每个条件。例如,在git status的输出中是否有未跟踪的文件,人们可能并不总是关心。

例如,要查看是否有任何局部的非阶段性变化,您可以查看的返回代码:

git diff --exit-code

要检查是否有任何暂存但未提交的更改,您可以使用的返回代码:

git diff --cached --exit-code

最后,如果你想知道你的工作树中是否有未被忽略的未跟踪文件,你可以测试以下命令的输出是否为空:

git ls-files --other --exclude-standard --directory

更新:您在下面询问是否可以更改该命令以排除输出中的目录。你可以通过添加--no-empty-directory来排除空目录,但要排除输出中的所有目录,我认为你必须过滤输出,例如:

git ls-files --other --exclude-standard --directory | egrep -v '/$'

-vegrep意味着只输出不匹配模式的行,并且模式匹配任何以/结尾的行。

虽然不漂亮,但很管用:

git status | grep -qF 'working directory clean' || echo "DIRTY"

不确定消息是否依赖于区域设置,所以可能会在前面放置LANG=C

在git源代码中有一个sh脚本,其中包括以下内容。

require_clean_work_tree () {
git rev-parse --verify HEAD >/dev/null || exit 1
git update-index -q --ignore-submodules --refresh
err=0


if ! git diff-files --quiet --ignore-submodules
then
echo >&2 "Cannot $1: You have unstaged changes."
err=1
fi


if ! git diff-index --cached --quiet --ignore-submodules HEAD --
then
if [ $err = 0 ]
then
echo >&2 "Cannot $1: Your index contains uncommitted changes."
else
echo >&2 "Additionally, your index contains uncommitted changes."
fi
err=1
fi


if [ $err = 1 ]
then
test -n "$2" && echo >&2 "$2"
exit 1
fi
}

这个片段显示了如何使用git diff-filesgit diff-index来查找之前已知的文件是否有任何更改。但是,它不允许您发现一个新的未知文件是否已添加到工作树中。

如果你和我一样,你想知道是否有:

1)更改现有文件 2)新增文件 3)删除文件

而且特别不想知道那些无法追踪的文件。

这应该做到:

git status --untracked-files=no --porcelain

下面是我的bash代码,用于在回购干净时退出脚本。它使用了untracked files选项的简写版本:

[[ -z $(git status -uno --porcelain) ]] && echo "this branch is clean, no need to push..." && kill -SIGINT $$;

可以将git status --porcelain与简单的grep结合起来执行测试。

if git status --porcelain | grep .; then
echo Repo is dirty
else
echo Repo is clean
fi

我有时会把它当做简单的一行代码:

# pull from origin if our repo is clean
git status --porcelain | grep . || git pull origin master

-qs添加到您的grep命令,使其静默。

我会做一个测试:

git diff --quiet --cached

或者这是明确的:

git diff --quiet --exit-code --cached

地点:

—退出代码

使用类似diff(1)的代码退出程序。也就是说,如果有差异,它以1退出,0表示没有差异。

——安静

禁用程序的所有输出。暗示—退出代码

我在一个脚本中使用这个:

  • 当一切都干净的时候
  • 1当有一个差异或未跟踪的文件

    [-z "$(git状态-瓷器)") < / p >

我在讨论中有点晚了,但如果只是你需要一个退出码为0,如果git status --porcelain不返回任何东西,并且!= 0否则,试试这个:

exit $( git status --porcelain | wc -l )

这将使行数成为退出代码,在超过255行的情况下可能会出现问题。所以

exit $( git status --porcelain | head -255 | wc -l )

将解释这一点;)

除了其他解决方案,你还可以有单独的命令(使用git log ranges),在获取之后告诉你需要拉,和/或你需要推。

如果你需要编写脚本:

[ "$(git log ..origin/main)" == "" ] || (
echo "something new on main"
.. pull ?
)
[ "$(git rev-list origin/main..)" == "" ] || (
echo "something new local"
.. push ?
)

更多细节在这篇文章

我发现当涉及到git子模块时,所有的答案都是无用的。

通过小调查,我找到了最好的解决方案,简单可靠:

git commit --dry-run && echo "Things to commit" || echo "Clean repo"

你可以添加-a,如果任何变化都需要考虑,而不仅仅是index(检测子模块也应该更新)。