我想写一个脚本,让我能够轻松地切换分支并保留当前的更改。
问题是如果当前存储库中没有更改。那么
git stash
go checkout main
git stash pop
问题是如果当前存储库中没有更改。那么
stash pop
将弹出以前的存储。有什么最简单的方法来检查是否有更改可以弹出?一种简单的方法是检查工作区是否有更改的文件,建立在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
的信息,请参考文档(有关wc
的信息请参阅相应的文档)。
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
}
git stash
是否会做任何事情,但实际上这并不是最好的选择:git stash
会做一些事情,首先它会重复这些测试(并且它们会说有什么可隐藏的内容),在这种情况下它们会发生两次。
- 如果“正确”的测试集合发生改变,您可能会错误地预测 git stash
的动作并陷入麻烦。git stash
,并跟踪其是否有任何操作。
2. 在目标分支上运行 git checkout
。
3. 如果 git stash
存储了一些内容,在运行 git stash pop
(或者首先运行 --apply --keep-index
,以查看是否有效,并只在必要时不使用 --keep-index
应用等待解决方法等)。git stash
的工作方式,以及有关git的“plumbing命令”的一些其他信息。在 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)
git stash
会将新的存储推送到堆栈上。 如果两个引用都为空,或者两个引用名称指向相同的提交,则git stash
不会执行任何操作:if [ "$old_stash" = "$new_stash" ]; then ...; else ...; fi
[ "$old_stash" != "$new_stash" ] && git stash pop
这些测试利用了两个空字符串相互等同的事实,在/bin/[
和shell内置程序的结果中,它们与任何非空字符串都不相等。
git status
git status --porcelain
是一种方法,虽然可能不是最好的(即最快的)。根据手册:
--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
完成类似的操作,但是由于计算差异需要比枚举状态更长时间,所以我不建议这样做。
/Projects/mathspace$ git stash 没有本地更改需要保存 (mathspace)chris@cl:/Projects/mathspace$ echo $? 0 - Casebashgit status
输出中隐藏未跟踪的文件,你可以使用--untracked-files=no
(或-uno
),请参考文档。 - Sascha Wolf