Git stash pop仅在成功隐藏之前
我的工作流程中有一部分涉及到以下方面:Git stash pop仅在成功隐藏之前,git,bash,Git,Bash,我的工作流程中有一部分涉及到以下方面: git隐藏更改 吉特拉力 流行音乐隐藏的变化 启动mergetool以解决冲突 我正在尝试编写一个脚本来同时完成所有这些事情,这样我就可以从终端调用它 #!/bin/bash # First stash our local changes git stash # Then git pull to update our repo git pull # Pop the stash git stash pop # Launch mergetool i
- git隐藏更改
- 吉特拉力
- 流行音乐隐藏的变化
- 启动mergetool以解决冲突
#!/bin/bash
# First stash our local changes
git stash
# Then git pull to update our repo
git pull
# Pop the stash
git stash pop
# Launch mergetool if necessary
git mergetool
我遇到的问题是,如果我意外地运行了它,并且对隐藏没有任何更改,
git stash pop
会应用一些(通常是超旧的)隐藏。我想做的是运行git stash pop
,前提是我之前确实隐藏了一些东西。有什么方法可以做到这一点吗?如果你在脚本中做很多事情,你应该尽量避免隐藏,而不是简单地提交代码,然后拉取更改
您还可以编写别名而不是脚本:
git config --global alias.<your alias> "git add. && git commit &1 && git pull"
git-config——全局别名。“git add.&git commit&1&&git pull”
上面的命令将接受提交消息作为参数,并执行git add、commit和pull操作首先运行git状态如何?如果有本地更改,请运行stash命令。如果没有,跳过它。将此结果保存在bool中,如果没有新的存储,则不要运行pop。阅读您对为什么要这样做的解释,我可能会选择完全不同的方法。首先,我将获取您要使用的遥控器:
git fetch <remote> (e.g. git fetch origin)
这样,合并后就不会执行自动提交。而且,可能更明智的做法是完全避免git隐藏在这里。例如,我会考虑使用单独的git fetch
和git rebase
步骤(参见Xavier的回答),并注意到rebase现在有--autostash
,它本质上就是做你想要的事情,只是不能通过git pull
便利脚本直接使用。1
也就是说,有一种方法可以满足你的要求。这有点棘手。如果git stash save
有一个类似于git commit--allow empty
的“force”选项,这会容易得多,但它没有这样的选项。2相反,您可以做的是检测git stash save
是否推送了一个新的存储。如果git stash save
有一个退出状态,指示它是否推送了一个隐藏,那么这也会容易得多,但是它没有。这意味着我们必须完全依靠另一种伎俩。我们从两个事实开始:git rev parse
从“引用”中查找SHA-1,而git stash
使用一个特定的引用
git rev parse
命令将任何引用转换为SHA-1:
$ git rev-parse refs/remotes/origin/master
2635c2b8bfc9aec07b7f023d8e3b3d02df715344
引用只是一个名称,通常以refs
开头,命名一些SHA-1 ID。最常见的是分支:refs/heads/branch
。您可能还使用了标记:refs/tags/tag
,并且可能使用了远程跟踪分支,如origin/master
,它是全名的缩写,refs/remotes/origin/master
stash
脚本使用refs/stash
,因此我们可以简单地运行git rev parse refs/stash
。3我们希望在git stash save
之前运行它,然后在git stash save
之后再次运行它。如果输出发生更改,那么git stash save
步骤必须已将新的存储推送到存储堆栈上
我们必须小心一点,因为如果存储堆栈为空(因为上一个存储在较早时被弹出或删除,或者还没有创建任何存储),git rev parse
将给出错误消息,并且不会生成SHA-1:
$ git rev-parse refs/stash
fatal: ambiguous argument 'refs/stash': unknown revision or path not in
the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
1git pull
命令基本上是git fetch
的简写,后跟git merge
,或者,如果您告诉它,运行git fetch
,后跟通常更合适的git rebase
。但是,如果您将其分为两个单独的步骤,您将获得更多的控制权,以及在合并或重定基址之前检查传入更改的能力
2您可以使用相对较新的create
和store
子命令有效地强制创建隐藏:创建一个隐藏,然后存储生成的SHA-1,即使没有任何要隐藏的内容,您也可以强制保存一个隐藏。但并不是每个人都了解最新的git,所以对于脚本来说,使用旧的方式可能更明智(或者如前所述,完全不要使用隐藏,特别是在不同版本的git中,它有各种小但令人讨厌的bug)
3拼写全名是明智的,因为git rev parse stash
将首先查找名为stash
的分支。在编写别名或脚本时,所有引用通常都是这样:拼写全名(并根据需要使用--
语法),以确保git在奇数情况下不会执行其认为的操作。使用git stash save
时,成功保存后将显示您传递的消息
因此,一个技巧是生成一个时间戳,它将用作消息,如果在生成的消息中找到了时间戳,则丢弃最近的隐藏
一行:
t=timestamp-$(date +%s); r=$(git stash save $t); v=$(echo $r|grep $t); if [ "$v" ]; then git stash list; echo "SAVED! NOW REMOVING..."; git stash drop stash@{0}; else echo "Nothing to Stash!"; fi; echo "Stashes: "; git stash list; echo "Done!"
扩大:
# unique timestamp
t=timestamp-$(date +%s)
# stash with message
r=$(git stash save $t)
# check if the value exists
v=$(echo $r|grep $t)
# if the message is found...
if [ "$v" ] then
# DEBUG: Before
git stash list
echo "SAVED! NOW REMOVING..."
# remove last stash
git stash drop stash@{0}
else
echo "Nothing to Stash!"
fi
# DEBUG: after
echo "Stash List: "
git stash list
echo "Done!"
我正在寻找类似的东西来自动合并主。我最终只是创建了一个具有唯一名称的空文件。下一步是在隐藏时包括未跟踪的文件(stash-u
)。现在我知道我可以随时弹出,因为我正在创造一些东西来隐藏。最后,我删除了我创建的新文件,其他的都完成了
然后,我创建了以下别名:
up - pull with rebase and sub-modules*
mm - merge master
tm - create file with novel name
rtm - remove said file
…以及实际别名:
[alias]
up = !git pull --rebase --prune --recurse-submodules $@ && git submodule update --init --recursive && git submodule foreach git up && echo 'git on up'
mm = "!f() { git tm; git stash -u; git co ${1-master}; git up; git co -; git merge ${1-master}; git stash pop; git rtm; }; f"
tm = "!f() { touch __nothing_to_see_here__; }; f"
rtm = "!f() { rm __nothing_to_see_here__; }; f"
*up from为什么需要隐藏步骤?如果我有与拉取冲突的本地更改,它会显示“错误:您对以下文件的本地更改将被合并覆盖:file.ext请提交更改或在合并之前将其隐藏。中止”。因此,隐藏、拉取,pop way允许我拉取更改,然后通过mergetool将其合并。那么为什么不简单呢
# unique timestamp
t=timestamp-$(date +%s)
# stash with message
r=$(git stash save $t)
# check if the value exists
v=$(echo $r|grep $t)
# if the message is found...
if [ "$v" ] then
# DEBUG: Before
git stash list
echo "SAVED! NOW REMOVING..."
# remove last stash
git stash drop stash@{0}
else
echo "Nothing to Stash!"
fi
# DEBUG: after
echo "Stash List: "
git stash list
echo "Done!"
up - pull with rebase and sub-modules*
mm - merge master
tm - create file with novel name
rtm - remove said file
[alias]
up = !git pull --rebase --prune --recurse-submodules $@ && git submodule update --init --recursive && git submodule foreach git up && echo 'git on up'
mm = "!f() { git tm; git stash -u; git co ${1-master}; git up; git co -; git merge ${1-master}; git stash pop; git rtm; }; f"
tm = "!f() { touch __nothing_to_see_here__; }; f"
rtm = "!f() { rm __nothing_to_see_here__; }; f"