我想编写一个脚本,允许我轻松更改分支,保持当前的更改。
git stash
go checkout main
git stash pop
问题是如果存储库中当前没有更改。然后stash pop
将弹出以前的藏匿处。检查pop是否有变化的最简单方法是什么?
答案 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
的更多信息,请查看documentation(respectively 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
的行为并陷入麻烦。显然,你想要的是:
git stash
,并跟踪这是否有效。git checkout
。git stash
隐藏了某些内容,请首先运行git stash pop
(或者--apply --keep-index
},看看是否可以解决这个问题,并且只在需要时才申请不使用--keep-index
等等。)。棘手的部分是第一步。事实证明这很简单,你只需要知道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
执行类似的操作,但由于计算差异可能比枚举任何实际存储库的状态要花费更长的时间,因此我不建议使用它。