检查Git是否以编程方式进行了更改

时间:2014-07-16 05:07:13

标签: git bash

我想编写一个脚本,允许我轻松更改分支,保持当前的更改。

git stash
go checkout main
git stash pop

问题是如果存储库中当前没有更改。然后stash pop将弹出以前的藏匿处。检查pop是否有变化的最简单方法是什么?

3 个答案:

答案 0 :(得分:6)

根据Chris Hayes建议,检查工作树中是否有更改文件的简单方法是git status --porcelain --untracked-files=no(替代-uno)和wc -l的组合。

这将为您提供已更改文件的数量。

这是一个应该满足您需求的脚本示例:

changed_files=$(git status --porcelain --untracked-files=no | wc -l)
[ $changed_files -gt 0 ] && git stash

< do work > 

[ $changed_files -gt 0 ] && git stash pop

有关git status的更多信息,请查看documentationrespectively for wc)。

答案 1 :(得分:5)

git stash is actually a shell (plain sh, not bash) script,所以你可以看一下它是做什么来决定是否要藏匿:

no_changes () {
        git diff-index --quiet --cached HEAD --ignore-submodules -- &&
        git diff-files --quiet --ignore-submodules &&
        (test -z "$untracked" || test -z "$(untracked_files)")
}

untracked_files () {
        excl_opt=--exclude-standard
        test "$untracked" = "all" && excl_opt=
        git ls-files -o -z $excl_opt
}

因此,您可以重复这些测试以查看git stash是否会执行任何操作 - 但这实际上不是最佳选择:

  • 如果git stash会做某事,首先它会重复这些测试(并且他们说有东西需要藏匿),这使得它们在这种情况下会发生两次。
  • 如果“正确”的测试集发生变化,您可能会错误预测git stash的行为并陷入麻烦。

显然,你想要的是:

  1. 运行git stash,并跟踪这是否有效。
  2. 在目标分支上运行git checkout
  3. 如果git stash隐藏了某些内容,请首先运行git stash pop(或者--apply --keep-index},看看是否可以解决这个问题,并且只在需要时才申请不使用--keep-index等等。)。
  4. 棘手的部分是第一步。事实证明这很简单,你只需要知道how git stash works,嗯,广泛的细节,以及关于git的“管道命令”的其他一些内容。您只需在git stash save步骤之前grab the previous stash stack top if any,然后抓住新的顶部(如果有),并进行比较:

    old_stash=$(git rev-parse -q --verify refs/stash)
    git stash save [additional arguments here if desired, e.g., -q]
    new_stash=$(git rev-parse -q --verify refs/stash)
    

    如果两个refs命名不同的提交,或者旧的ref为空并且new不为空,则git stash在堆栈上推送一个新的存储。如果两个引用都是空的,或者两个引用命名相同的提交,那么git stash什么都不做:

    if [ "$old_stash" = "$new_stash" ]; then ...; else ...; fi
    

    或者,在您的情况下,或许更像是:

    [ "$old_stash" != "$new_stash" ] && git stash pop
    

    (根据/bin/[和shell的内置结果,这些测试利用了两个空字符串彼此相等,并且不等于任何非空字符串的事实副本)。

答案 2 :(得分:4)

使用git status

git status --porcelain是一种方式,虽然可能不是最好的(即最快)。从手册页:

  

- 瓷

     

以易于解析的格式为脚本提供输出。这类似于短输出,但在Git中保持稳定   版本,无论用户配置如何。有关详细信息,请参阅下文。

用法示例:

$ git status --porcelain

M tmp/myfile.c

$ git stash
$ git status --porcelain
$ 

如果没有变化,git status --porcelain没有输出。但有一个缺陷 - 新文件将显示为?? newfile.txt,因此您可能必须对输出进行后处理以获得所需内容,因为新文件不会被隐藏:

$ git status --porcelain
?? newfile.txt

$ git status --porcelain | grep -v "^\?\?"
$

您可以使用git diff执行类似的操作,但由于计算差异可能比枚举任何实际存储库的状态要花费更长的时间,因此我不建议使用它。