如何以编程方式确定是否存在未提交的更改?

问题描述 投票:190回答:8

在Makefile中,我想,如果有未提交的更改执行某些操作(无论是在工作树或指数)。什么是做到这一点的最清洁和最有效的方法是什么?与在一个情况下,在其他的返回值为零和非零退出命令会适合我的目的。

我可以运行git status和管道通过grep输出,但我觉得必须有一个更好的办法。

git
8个回答
259
投票

更新:OP Daniel Stutzbach指出in the comments,这个简单的命令git diff-index为他工作:

git diff-index --quiet HEAD --

然后,您可以看到“How to check if a command succeeded?”如果你是在一个bash脚本使用它:

git diff-index --quiet HEAD -- || echo "untracked"; // do something about it

注:如由commented Anthony Sottile

git diff-index HEAD ...将无法在其上没有提交(如新初始化库)的一个分支。 一个解决办法,我发现是git diff-index $(git write-tree) ...

haridsv指出in the commentsgit diff-files上一个新的文件并没有检测到它作为一个差异。 比较安全的做法似乎是在文件规范首先运行git add然后用git diff-index看看是否有什么得到了运行git commit前添加到索引。

git add ${file_args} && \
git diff-index --cached --quiet HEAD || git commit -m '${commit_msg}'

原来的答案:

“编程”意味着永远依靠porcelain commands。 始终依靠plumbing commands

请参阅替代品(如Checking for a dirty index or untracked files with Git)也“git status --porcelain

你可以把灵感from the new "require_clean_work_tree function" which is written as we speak;)(2010年10月上旬)

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
}

85
投票

而其他的解决方案是非常彻底的,如果你想获得真正的快速和肮脏的,尝试这样的事情:

[[ -z $(git status -s) ]]

它只是检查是否有在状态摘要存在任何输出。


53
投票

qazxsw POI将返回非零,如果有任何变化; qazxsw POI是没有输出相同。既然你要检查工作树和索引,使用

git diff --exit-code

要么

git diff --quiet

任何一个可以告诉你,如果有上演或不提交的更改。


14
投票

扩大对@ Nepthar的回答:

git diff --quiet && git diff --cached --quiet

4
投票

正如在其他的答案指出,就这么简单这样的命令就足够了:

git diff --quiet HEAD

如果省略了最后两个破折号,如果你有一个名为if [[ -z $(git status -s) ]] then echo "tree is clean" else echo "tree is dirty, please commit changes before running this" exit fi 文件的命令就会失败。

例:

git diff-index --quiet HEAD --

谨慎的字:此命令忽略未跟踪文件。


3
投票

我创造了一些方便的git的别名,列出未分级和筹备的文件:

HEAD

然后,你可以轻松地做这样的事情:

#!/bin/bash
set -e
echo -n "Checking if there are uncommited changes... "
trap 'echo -e "\033[0;31mFAILED\033[0m"' ERR
git diff-index --quiet HEAD --
trap - ERR
echo -e "\033[0;32mAll set!\033[0m"

# continue as planned...

你可以使其更具可读性在您的git config --global alias.unstaged 'diff --name-only' git config --global alias.staged 'diff --name-only --cached' 称为[[ -n "$(git unstaged)" ]] && echo unstaged files || echo NO unstaged files [[ -n "$(git staged)" ]] && echo staged files || echo NO staged files 地方创建一个脚本:

PATH

现在上述实施例可以被简化为:

git-has

为了完整这里有未跟踪或忽略的文件类似的别名:

#!/bin/bash
[[ $(git "$@" | wc -c) -ne 0 ]]

0
投票

使用Python和GitPython:

git has unstaged && echo unstaged files || echo NO unstaged files
git has staged && echo staged files || echo NO staged files

如果存储库不干净,则返回True


-3
投票

这里是最好的,最彻底的方法。

git config --global alias.untracked 'ls-files --exclude-standard --others'
git config --global alias.ignored 'ls-files --exclude-standard --others --ignored'
© www.soinside.com 2019 - 2024. All rights reserved.