require_clean_work_tree () {
# Update the index
git update-index -q --ignore-submodules --refresh
err=0
# Disallow unstaged changes in the working tree
if ! git diff-files --quiet --ignore-submodules --
then
echo >&2 "cannot $1: you have unstaged changes."
git diff-files --name-status -r --ignore-submodules -- >&2
err=1
fi
# Disallow uncommitted changes in the index
if ! git diff-index --cached --quiet HEAD --ignore-submodules --
then
echo >&2 "cannot $1: your index contains uncommitted changes."
git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2
err=1
fi
if [ $err = 1 ]
then
echo >&2 "Please commit or stash them."
exit 1
fi
}
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
}
使用提供的git status --porcelain,即设计为机器可解析,尽管有些人(错误地)在评论中表示相反。如果在git status中出现了一些东西,那么我就认为工作目录是脏的。所以我用[ -z "$(git status --porcelain=v1 2>/dev/null)" ]测试洁净度,如果在git目录外运行,它也会通过。
灵感来自这个答案。你grepgit status --porcelain=v1输出的行。每行的前两个字符表示特定文件的状态。在grepping之后,通过将输出输出输送到wc -l来计算有多少行处于这种状态,wc -l会计算行数。
例如,如果在git存储库中运行,这个脚本将打印一些信息。
#!/bin/sh
GS=$(git status --porcelain=v1 2>/dev/null) # Exit code 128 if not in git directory. Unfortunately this exit code is a bit generic but it should work for most purposes.
if [ $? -ne 128 ]; then
function _count_git_pattern() {
echo "$(grep "^$1" <<< $GS | wc -l)"
}
echo "There are $(_count_git_pattern "??") untracked files."
echo "There are $(_count_git_pattern " M") unstaged, modified files."
echo "There are $(_count_git_pattern "M ") staged, modified files."
fi
if output="$(git status --porcelain)" && [ -z "$output" ]; then
# `git status --porcelain` had no errors AND the working directory is clean
echo "'git status --porcelain' had no errors AND the working directory" \
"is clean."
else
# Working directory has uncommitted changes.
echo "Working directory has UNCOMMITTED CHANGES."
fi
第一部分,如果git status --porcelain命令有错误,if output=$(git status --porcelain)将失败并跳转到else子句。第二部分&& [ -z "$output" ]测试output变量是否包含空字符串(zero-length)。如果是,那么git status是干净的,没有任何变化。
选项2
然而,通常我更喜欢的用法是用-n(非零)而不是-z(零)来否定测试,并像这样做:
if output="$(git status --porcelain)" && [ -n "$output" ]; then
echo "'git status --porcelain' had no errors AND the working directory" \
"is dirty (has UNCOMMITTED changes)."
# Commit the changes here
git add -A
git commit -m "AUTOMATICALLY COMMITTING UNCOMMITTED CHANGES"
fi
选项3
一种更细粒度的方式来编写上面的第一个代码块是这样的:
if ! git_status_output="$(git status --porcelain)"; then
# `git status` had an error
error_code="$?"
echo "'git status' had an error: $error_code"
# exit 1 # (optional)
elif [ -z "$git_status_output" ]; then
# Working directory is clean
echo "Working directory is clean."
else
# Working directory has uncommitted changes.
echo "Working directory has UNCOMMITTED CHANGES."
# exit 2 # (optional)
fi