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

Cas*_*ash 2 git bash

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

git stash
go checkout main
git stash pop
Run Code Online (Sandbox Code Playgroud)

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

Sas*_*olf 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
Run Code Online (Sandbox Code Playgroud)

有关更多信息,git status请查看文档(分别为wc).


tor*_*rek 5

git stash实际上是一个shell(简单的sh,而不是bash)脚本,所以你可以看看它是做什么来决定是否要存储:

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

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

  • 如果git stash会做某事,首先它重复这些测试(并且他们说有东西要藏匿),这使得它们在这种情况下发生两次.
  • 如果"正确"的一组测试发生变化,你就会错误预测git stash行动并陷入困境.

显然,你想要的是:

  1. 运行git stash,并跟踪这是否做了什么.
  2. git checkout在目标分支上运行.
  3. 如果git stash隐藏某些东西,运行git stash pop(或者--apply --keep-index首先,看看是否可以解决这个问题,并且--keep-index不仅在需要时使用,等等).

棘手的部分是第一步.结果很简单,你只需要知道如何git stash工作,嗯,广泛的细节,以及关于git的"管道命令"的其他一些内容.你只需在步骤之前抓住前面的藏匿堆栈顶部git stash save,然后抓住新的顶部(如果有的话),并比较:

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

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

if [ "$old_stash" = "$new_stash" ]; then ...; else ...; fi
Run Code Online (Sandbox Code Playgroud)

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

[ "$old_stash" != "$new_stash" ] && git stash pop
Run Code Online (Sandbox Code Playgroud)

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