我如何检查我的git存储库中是否有任何未提交的更改:
添加到索引但未提交的更改 无路径的文件
从一个脚本?
git-status在git 1.6.4.2版本中似乎总是返回0。
我如何检查我的git存储库中是否有任何未提交的更改:
添加到索引但未提交的更改 无路径的文件
从一个脚本?
git-status在git 1.6.4.2版本中似乎总是返回0。
为什么不封装'git状态与一个脚本:
将分析该命令的输出 是否会根据需要返回适当的错误代码
这样,您就可以在脚本中使用“增强”状态。
正如0xfe在他的精彩回答中提到的,git状态—瓷器在任何基于脚本的解决方案中都是重要的
--porcelain
为脚本提供稳定、易于解析的输出格式。 目前这与——short输出相同,但保证将来不会更改,因此对脚本是安全的。
好时机!几天前我写了一篇关于这方面的博客文章,当时我想出了如何在提示符中添加git状态信息。
我是这么做的:
对于脏状态: 如果当前git分支是脏的,则返回“*”。 函数evil_git_dirty { [[$ (git diff, shortstat 2 > / dev / null |尾巴n1 ) != "" ]] && 回声“*” } 对于未跟踪的文件(请注意git状态的——porcelain标志,它会为您提供良好的可解析输出): 返回未跟踪文件的数量 函数evil_git_num_untracked_files { Expr ' git status——porcelain 2>/dev/null| grep "^??"| wc -l ' }
虽然git diff——shortstat更方便,但你也可以使用git status——porcelain来获取脏文件:
# Get number of files added to the index (but uncommitted)
expr $(git status --porcelain 2>/dev/null| grep "^M" | wc -l)
# Get number of files that are uncommitted and not added
expr $(git status --porcelain 2>/dev/null| grep "^ M" | wc -l)
# Get number of total uncommited files
expr $(git status --porcelain 2>/dev/null| egrep "^(M| M)" | wc -l)
注意:2>/dev/null会过滤掉错误消息,所以你可以在非git目录上使用这些命令。(它们将简单地为文件计数返回0。)
编辑:
以下是这些帖子:
在终端提示中添加Git状态信息
改进了启用git的Shell提示符
一个DIY的可能性,更新遵循0xfe的建议
#!/bin/sh
exit $(git status --porcelain | wc -l)
正如Chris Johnsen所指出的,这只适用于Git 1.7.0或更新版本。
可靠地“脚本化”Git的关键是使用“管道”命令。
The developers take care when changing the plumbing commands to make sure they provide very stable interfaces (i.e. a given combination of repository state, stdin, command line options, arguments, etc. will produce the same output in all versions of Git where the command/option exists). New output variations in plumbing commands can be introduced via new options, but that can not introduce any problems for programs that have already been written against older versions (they would not be using the new options, since they did not exist (or at least were not used) at the time the script was written).
不幸的是,“日常”Git命令是“瓷器”命令,所以大多数Git用户可能不熟悉管道命令。瓷器和管道命令之间的区别是在git的主要manpage中做出的(参见高级命令(瓷器)和低级命令(管道)的子章节。
要找出未提交的更改,你可能需要git diff-index(比较索引(可能是工作树的跟踪位)和一些其他树(例如HEAD)),可能是git diff-files(比较工作树和索引),可能是git ls-files(列表文件;例如,列出未跟踪、未忽略的文件)。
(注意,在下面的命令中,使用HEAD——而不是HEAD,否则如果有一个名为HEAD的文件,命令就会失败。)
要检查存储库是否有阶段性更改(尚未提交),请使用以下命令:
git diff-index --quiet --cached HEAD --
如果它以0退出,则没有差异(1表示有差异)。
要检查工作树是否有可以阶段性的更改:
git diff-files --quiet
退出代码与git的diff-index相同(0 ==没有区别;1 ==差异)。
检查工作树中索引和被跟踪文件的组合是否对HEAD有变化:
git diff-index --quiet HEAD --
这就像是前两者的结合。一个主要的区别是,如果您在工作树中“撤消”了一个阶段性的更改(回到HEAD中的内容),它仍然会报告“无差异”。在同样的情况下,两个单独的命令都将返回“存在差异”的报告。
您还提到了未跟踪文件。您可能指的是“未跟踪和未忽略”,也可能只是简单的“未跟踪”(包括被忽略的文件)。不管怎样,git ls-files都是完成这项工作的工具:
对于“untracked”(将包括被忽略的文件,如果存在):
git ls-files --others
对于“untracked and unignored”:
git ls-files --exclude-standard --others
我的第一个想法是检查这些命令是否有输出:
test -z "$(git ls-files --others)"
如果它以0退出,则没有未跟踪的文件。如果它以1退出,则存在未跟踪的文件。
这有很小的可能会将git ls-files中的异常退出转换为“no untracked files”报告(两者都会导致上述命令的非零退出)。更健壮的版本可能是这样的:
u="$(git ls-files --others)" && test -z "$u"
这个想法与前面的命令相同,但是它允许来自git ls-files的意外错误传播出去。在这种情况下,非零退出可能意味着“有未跟踪的文件”,也可能意味着发生了错误。如果你想要“error”结果与“no untracked files”结果相结合,使用test -n "$u"(其中exit为0表示“一些未跟踪的文件”,non- 0表示错误或“no untracked files”)。
另一种想法是使用——error-unmatch在没有未跟踪文件时导致非零退出。这也存在将“没有未跟踪文件”(退出1)与“发生错误”(退出非零,但可能是128)混为一谈的风险。但是检查0、1和非0退出码可能相当健壮:
git ls-files --others --error-unmatch . >/dev/null 2>&1; ec=$?
if test "$ec" = 0; then
echo some untracked files
elif test "$ec" = 1; then
echo no untracked files
else
echo error from ls-files
fi
如果您想只考虑未跟踪和未忽略的文件,以上任何git ls-files示例都可以采用——exclude-standard。
假设你使用的是git 1.7.0或更高版本…
在阅读了本页上的所有答案并进行了一些实验后,我认为将正确性和简洁性正确结合的方法是:
test -n "$(git status --porcelain)"
虽然git允许在跟踪、忽略、未跟踪但未忽略等内容之间有很多细微差别,但我相信典型的用例是用于自动化构建脚本,如果签出不干净,您希望停止所有内容。
在这种情况下,模拟程序员将要做的事情是有意义的:键入git status并查看输出。但我们不想依赖于特定的单词显示,所以我们使用了1.7.0中引入的——porcelain模式;启用干净目录时,不会产生任何输出。
然后使用test -n查看是否有输出。
如果工作目录是干净的,该命令将返回1,如果有要提交的更改,则返回0。你可以把-n改成-z。这对于将其链接到脚本中的命令非常有用。例如:
test -z "$(git status --porcelain)" || red-alert "UNCLEAN UNCLEAN"
这实际上是在说“要么不需要做出改变,要么就会拉响警报”;这个一行语句可能比if语句更可取,这取决于您正在编写的脚本。
这是一个更加shell友好的变体,用于查找存储库中是否存在任何未跟踪的文件:
# Works in bash and zsh
if [[ "$(git status --porcelain 2>/dev/null)" = *\?\?* ]]; then
echo untracked files
fi
这不会派生第二个进程grep,并且不需要检查您是否在git存储库中。这对于shell提示等很方便。
这个帖子可能会有更好的答案组合。但这对我有用……对于你的.gitconfig的[alias]部分…
# git untracked && echo "There are untracked files!"
untracked = ! git status --porcelain 2>/dev/null | grep -q "^??"
# git unclean && echo "There are uncommited changes!"
unclean = ! ! git diff --quiet --ignore-submodules HEAD > /dev/null 2>&1
# git dirty && echo "There are uncommitted changes OR untracked files!"
dirty = ! git untracked || git unclean
我使用最简单的自动测试来检测脏状态=任何更改,包括未跟踪的文件:
git add --all
git diff-index --exit-code HEAD
备注:
如果没有add——all, diff-index不会注意到未跟踪的文件。 通常情况下,我在测试错误代码后运行git重置来取消所有内容。 考虑用quiet代替exit-code来避免输出。
你也可以
git describe --dirty
. 如果它检测到一个肮脏的工作树,它将在结尾附加单词“-dirty”。根据git-describe(1):
--dirty[=<mark>]
Describe the working tree. It means describe HEAD and appends <mark> (-dirty by default) if
the working tree is dirty.
. 注意:未跟踪的文件不被认为是“脏文件”,因为,正如manpage声明的那样,它只关心工作树。
看了一下这些答案…(在*nix和windows上有各种问题,这是我的要求)…发现以下方法效果很好…
git diff --no-ext-diff --quiet --exit-code
检查*nix中的退出代码
echo $?
#returns 1 if the repo has changes (0 if clean)
查看窗口$中的退出代码
echo %errorlevel%
#returns 1 if the repos has changes (0 if clean)
来源:https://github.com/sindresorhus/pure/issues/115 感谢@paulirish的分享
这是最好、最干净的方法。由于某些原因,所选的答案对我不起作用,它没有拾取未提交的新文件所进行的更改。
function git_dirty {
text=$(git status)
changed_text="Changes to be committed"
untracked_files="Untracked files"
dirty=false
if [[ ${text} = *"$changed_text"* ]];then
dirty=true
fi
if [[ ${text} = *"$untracked_files"* ]];then
dirty=true
fi
echo $dirty
}
我经常需要一种简单的方法让构建失败,如果在执行结束时有任何被修改的跟踪文件或任何未被忽略的未跟踪文件。
这对于避免构建产生剩余的情况非常重要。
到目前为止,我使用的最好的命令是这样的:
test -z "$(git status --porcelain | tee /dev/fd/2)" || \
{{ echo "ERROR: git unclean at the end, failing build." && return 1 }}
它可能看起来有点复杂,如果有人能找到一个短的变种,我会很感激 保持所期望的行为:
如果一切正常,则没有输出和成功退出代码 如果失败,退出代码1 stderr上的错误消息解释了它失败的原因 显示导致失败的文件列表,再次stderr。
@eduard- wch的回答很完整,但因为我想同时检查两者,这里是我的最后一个变体。
set -eu
u="$(git ls-files --others)"
if ! git diff-index --name-only --quiet HEAD -- || [ -z "${u:-}" ]; then
dirty="-dirty"
fi
当不使用set -e或类似的方法执行时,我们可以执行u="$(git ls-files——others)"|| exit 1(如果对已使用的函数有效,则返回)
因此,untracked_files仅在命令成功时设置。
之后,我们可以检查这两个属性,并设置一个变量(或任何东西)。