如果我的本地Git存储库有更改,我如何签入Bash脚本?

kmi*_*ndi 152 git

有些脚本在检查更改时无法正常工作.

我试过这样的:

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
Run Code Online (Sandbox Code Playgroud)

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

我正在为版本创建脚本(我在这里找到的地方)做这一切.

小智 254

使用git status:

cd /git/directory
if [[ `git status --porcelain` ]]; then
  # Changes
else
  # No changes
fi
Run Code Online (Sandbox Code Playgroud)

  • 忽略未跟踪的文件:**如果[[`git status --porcelain --ntracked-files = no`]]; 然后** (21认同)
  • 最好的答案,令人遗憾的是,来自'shell和git架构师'的答案更受到高度评价. (13认同)
  • 对我来说,即使 git 状态非空,条件也总是进入“无更改”情况。它是通过使用 `if [ -n "$(git status --porcelain)" ]; 修复的 那么`。 (6认同)
  • **这段代码的作用:** 执行 `git status --porcelain` 查看输出是否为空。如果是这样,则意味着存在变化。 (4认同)
  • 这很好,因为它考虑到无版本的文件,也使用瓷器,它应该与不同的git版本更兼容. (3认同)
  • 用于检查局部变化 - >```if [[$(git status --porcelain | wc -l)-gt 0]]; 然后echo CHANGED else echo NOT CHANGED local fi``` (3认同)
  • 检查命令的标准输出是否为空不是更好吗? (2认同)

Cas*_*bel 178

你正在做什么几乎可以工作:$CHANGED如果它是空的你应该引用,并且-z测试为空,这意味着没有变化.你的意思是:

if [ -n "$CHANGED" ]; then
    VN="$VN-mod"
fi
Run Code Online (Sandbox Code Playgroud)

Git的引用GIT-VERSION-GEN:

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

看起来你正在复制它,但你只是忘记了引用的细节.

当然,你也可以这样做:

if git diff-index --quiet HEAD --; then
    # No changes
else
    # Changes
fi
Run Code Online (Sandbox Code Playgroud)

或者,如果你只关心"有所改变"的情况:

if ! git diff-index --quiet HEAD --; then
    VN="$VN-mod"
fi
Run Code Online (Sandbox Code Playgroud)

使用--quietGit可以在遇到单个差异时立即停止处理,因此可能不必检查整个工作树.

  • 令人惊讶的[bash完成脚本](http://git.kernel.org/?p=git​​/git.git;a=blob_plain;f=contrib/completion/git-completion.bash;hb=HEAD)似乎正在使用`git diff --no-ext-diff --quiet --exit-code`来确定脏状态. (9认同)
  • 这对我不起作用,因为它不报告未跟踪的文件 (4认同)
  • @mjs:这确实是一个寻找这样的事情的好地方!该`--no-EXT-diff`选项适用于安全(万一有人已经配置了外置的区别司机),尽管`--exit-code`不应该是必要的,因为它是由`--quiet暗示`. (3认同)
  • 嗨,这是一个问题的最佳答案之一,你刚刚给了我所需的所有信息以及我需要的其他信息:).我只需要最后一个,"有些东西已经改变了":)你是对的,我复制了它. (2认同)
  • 即使只有文件修改时间(而不是其内容)发生了变化,“git diff-index”也会报告更改。如果你“触摸”一个文件,它将报告修改,运行“git status”将重置。使用下面的 `git status` 会更好。 (2认同)

Arr*_*ter 16

虽然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
}
Run Code Online (Sandbox Code Playgroud)


jto*_*mpl 11

我在 Stack Overflow 上查找了数十个答案,但似乎没有一个能满足我的期望。也就是说,如果出现以下情况,脚本应该出错:

  • 当前本地状态与origin/master(包括:对现有文件的更改;新的未提交和已提交的文件以及文件删除)之间存在任何差异,或者
  • 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
Run Code Online (Sandbox Code Playgroud)

解释:

  • git status --porcelain将呈现尚未提交的文件列表。[[ -z "$(...)" ]]如果命令返回非空字符串,则用 包裹起来会出错。
  • git diff --exit-code master > /dev/nullmaster如果您当前提交的存储库状态与分支不同,将会出错。
  • git diff --exit-code origin/master..master > /dev/nullmaster如果您当前的分支与 不同,将会出错origin/master

例如,如果您想确保您的存储库可以安全地删除/清除,这非常有用。

为什么这样更好?

  • 答案仅依赖于git diff --exit-code ...不会出错;
  • 仅依赖的答案git status --porcelain不会告诉您您有尚未推送到远程的提交。


小智 7

OP的问题已经有9年多了。我不知道man git-status当时说了什么,但现在是这样的:

--porcelain[=<version>]  
Give the output in an easy-to-parse format for scripts. This is similar to the 
short output, but will remain stable across Git versions and regardless of user 
configuration. See below for details.  

The version parameter is used to specify the format version. This is optional and 
defaults to the original version v1 format.  
Run Code Online (Sandbox Code Playgroud)

这表明该--porcelain参数非常适合测试回购状态的更改。

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

我认为它本身bash没有布尔数据类型,但这可能足够接近:

--porcelain[=<version>]  
Give the output in an easy-to-parse format for scripts. This is similar to the 
short output, but will remain stable across Git versions and regardless of user 
configuration. See below for details.  

The version parameter is used to specify the format version. This is optional and 
defaults to the original version v1 format.  
Run Code Online (Sandbox Code Playgroud)

这可以重新转换为脚本的形式,或者在 git repo 文件夹中if-then-else通过 CLI 按原样执行。否则,请使用带有路径规范的选项到感兴趣的存储库:-C

[ -z "`git status --porcelain`" ] && echo "NULL-NO DIFFS" || echo "DIFFS EXIST"
Run Code Online (Sandbox Code Playgroud)

附录:

  1. 一些人建议使用该-u, --untracked-file选项来避免报告人们希望忽略的文件的状态。请注意,这会带来一个不幸的副作用:新添加的文件也不会显示状态。该选项在某些情况下很有用,但在使用前请仔细考虑。


ole*_*nko 7

我的 2 美分:

git status --porcelain | head -1
Run Code Online (Sandbox Code Playgroud)

仅返回一行而不是一长串


Leo*_*man 6

我有类似的问题,但我还要检查添加的文件.所以我做了以下事情:

cd /local/repo
RUN=0
git diff --no-ext-diff --quiet --exit-code || RUN=1
if [ $RUN = 0 ]; then
    RUN=`git ls-files --exclude-standard --others| wc -l`
fi

if [ $RUN = 0 ]; then
    exit 0
fi
Run Code Online (Sandbox Code Playgroud)


bla*_*acx 6

这也有效:

if [ $(git status --porcelain | wc -l) -eq "0" ]; then
  echo "   Git repo is clean."
else
  echo "   Git repo dirty. Quit."
  exit 1
fi
Run Code Online (Sandbox Code Playgroud)


And*_*ewD 5

git status 是你的朋友

转到Git目录git status以工作:

cd c:/path/to/.git
Run Code Online (Sandbox Code Playgroud)

设置变量以设置工作树,这样就不会出现“此操作必须在工作树中运行”错误:

WORKTREE=c:/path/to/worktree
Run Code Online (Sandbox Code Playgroud)

git status输出捕获到Bash变量中

--porcelain保证标准格式且可解析的用途:

CHANGED=$(git --work-tree=${WORKTREE} status --porcelain)
Run Code Online (Sandbox Code Playgroud)

如果-n(不为null),则有更改。

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

else
  echo 'not changed';
fi
Run Code Online (Sandbox Code Playgroud)