有些脚本在检查更改时不能正确工作。

我是这样试的:

VN=$(git describe --abbrev=7 HEAD 2>/dev/null)

git update-index -q --refresh
CHANGED=$(git diff-index --name-only HEAD --)
if [ ! -z $CHANGED ];
    then VN="$VN-mod"
fi

是否存在某种布尔检查,自上次提交以来是否有更改,或者我如何真正测试本地存储库是否有新的更改?

我所做的所有这些都是为了一个版本创建脚本(我在这里的某个地方找到的)。


当前回答

Git状态是你的朋友

切换到Git目录,Git状态可以正常工作:

cd c:/path/to/.git

设置一个变量来设置工作树,这样你就不会得到“这个操作必须在工作树中运行”错误:

WORKTREE=c:/path/to/worktree

在Bash变量中捕获git状态输出

使用-瓷器,保证在一个标准的格式和可分析:

CHANGED=$(git --work-tree=${WORKTREE} status --porcelain)

如果-n(非空),则有更改。

if [ -n "${CHANGED}" ]; then
  echo 'changed';

else
  echo 'not changed';
fi

其他回答

我查阅了很多Stack Overflow的答案,但没有一个符合我的期望。也就是说,如果出现以下情况,脚本会出错:

当前本地状态与原始/主文件之间有任何差异(包括:对现有文件的更改;新建未提交和已提交的文件,以及文件删除),或 Master有尚未推送到origin/ Master的提交。

最后的脚本可以这样使用:

if ! (git diff --exit-code origin/master..master > /dev/null) \
  || ! (git diff --exit-code master > /dev/null) \
  || ! [[ -z "$(git status --porcelain)" ]] ; then
  echo "Your local repo has some changes that aren't pushed to origin/master ."
  exit 1
fi

解释:

Git状态——瓷器将呈现尚未提交的文件列表。用[[-z "$(…)"如果命令返回了一个非空字符串,]]将会出错。 Git diff——exit-code master > /dev/null如果你当前提交的回购状态与主分支不同将会出错。 Git diff——exit-code origin/master..Master > /dev/null如果您当前的主分支与原点/主分支不同,将会出错。

这是有用的,例如,如果你想确保你的回购可能是安全的删除/清除。

为什么这样更好呢?

答案只依赖于git diff -exit-code…不会错误,如果你有新的未提交的非存储文件; 仅依赖于git状态的答案——porcelain不会告诉您有尚未推送到远程的提交。

虽然Jefromi的回答很好,但我发布这篇文章只是为了参考。

在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
}

您所做的几乎可以工作:如果它是空的,您应该引用$CHANGED,而-z测试为空,这意味着没有更改。你的意思是:

if [ -n "$CHANGED" ]; then
    VN="$VN-mod"
fi

引用Git的Git - version - gen:

git update-index -q --refresh
test -z "$(git diff-index --name-only HEAD --)" ||
VN="$VN-dirty"

看起来你是在抄袭,但你忘记了引用的细节。

当然,你也可以这样做:

if git diff-index --quiet HEAD --; then
    # No changes
else
    # Changes
fi

或者如果你只关心“某事发生了变化”的情况:

if ! git diff-index --quiet HEAD --; then
    VN="$VN-mod"
fi

使用——quiet的好处是Git可以在遇到单个差异时立即停止处理,因此它可能不需要检查整个工作树。

我是这样做的……

CHANGES=`git status | grep "working directory clean"`
if [ ! CHANGES -eq "" ] then
    # do stuff here
else
    echo "You have uncommitted changes..."
fi

Ansible的解决方案:

- name: Bootstrap checks
  block:
  - shell: "git status --porcelain"
    register: git_status
  - fail:
      msg: "Please clean git status: {{ git_status.stdout }}"
    when: git_status.stdout != ""