我的工作流程的一部分涉及做很多事情:
我正在尝试编写一个脚本来同时执行所有这些操作,因此我可以从终端调用它。
#!/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
。有没有办法做到这一点?
答案 0 :(得分:7)
作为Xavier Álvarez noted和codeWizard wrote,在这里完全避免git stash
可能更明智。例如,我会考虑使用单独的git fetch
和git rebase
步骤(请参阅Xavier的答案),并注意到rebase现在有--autostash
这基本上就是你想要的,它只是不直接可通过git pull
便利脚本获取。 1
那就是说, 是一种做你所问过的方法。这有点棘手。如果git stash save
具有类似于git commit --allow-empty
的“强制”选项会更容易,但它没有这样的选项。 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
步骤必须将新存储推送到存储堆栈。
我们必须要小心一点,因为如果存储堆栈是空的(因为最后一个存储被先前弹出或删除,或者还没有创建过stashes),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>...]'
因此我们实际上需要git rev-parse -q --verify refs/stash
,如果引用不存在,它会默默地产生任何内容,然后我们只需要在任何使用结果的shell脚本中小心一点:
oldsha=$(git rev-parse -q --verify refs/stash)
git stash -q save # add options as desired here
newsha=$(git rev-parse -q --verify refs/stash)
if [ "$oldsha" = "$newsha" ]; then
made_stash_entry=false
else
made_stash_entry=true
fi
... all of your other code goes here ...
if $made_stash_entry; then git stash pop; fi
1 git pull
命令基本上是git fetch
的简写,后跟git merge
,或者,如果你告诉它,运行{{1}接下来是通常更合适的git fetch
。但是,如果将其分解为两个单独的步骤,则可以获得更多控制权,以及在合并或重新定位之前检查传入更改的能力。
2 您可以使用相对较新的git rebase
和create
子命令有效地强制存储创建:创建一个存储,然后存储生成的SHA-1,然后你就可以了即使没有任何东西可以藏匿,也会被迫藏匿。但并不是每个人都对最新的git有所了解,所以对于脚本来说,依旧的方式可能更明智(或者如前所述,根本不使用藏匿,特别是因为它有各种各样的小但烦人的bug,各种版本git)。
3 拼出全名是明智的,因为store
将首先查找名为git rev-parse stash
的分支。在编写别名或脚本时,所有引用都是如此:拼出全名(并根据需要使用stash
语法)以确保git不会执行认为的意思,在奇怪的角落里。
答案 1 :(得分:3)
阅读你为什么做你做的事情的解释我可能会采取完全不同的方法。首先,我获取你想要使用的遥控器:
git fetch <remote> (e.g. git fetch origin)
然后,我会针对该遥控器的特定分支执行 rebase :
git rebase <remote>/<branch> (e.g. git rebase origin/master)
这将合并您的更改,您仍然可以解决任何冲突。
如果您不喜欢这种方法,您可能希望将 git pull 与 - no-commit 标志一起使用:
git pull --no-commit
这样,合并后不会执行自动提交。
答案 2 :(得分:3)
使用git stash save <messsage>
时,您传递的信息会在成功保存时显示。
因此,一个技巧是生成一个时间戳,该时间戳将用作消息,如果在结果消息中找到时间戳,则删除最新的存储。
一行:
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!"
答案 3 :(得分:1)
首先运行git状态怎么样?如果存在本地更改,请运行stash命令。如果没有,请跳过它。将此结果保存在bool中,如果没有新的藏匿,则不要运行pop。
答案 4 :(得分:0)
如果你在脚本中做很多事情,你应该尽量避免藏匿,而只需提交你的代码,然后提取你的更改。
您也可以编写别名而不是脚本:
git config --global alias.<your alias> "git add. && git commit &1 && git pull"
上面的命令将接受提交消息作为参数,并将执行git add,commit&amp;拉
答案 5 :(得分:0)
我正在寻找类似的东西来自动合并母版。我最终只是创建一个具有唯一名称的空文件。下一步是在存储(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"
* haacked起被盗