在git rebase上自动隐藏保存/弹出更改?
我的git工作流经常使用rebase。我总是获取上游更改(我分叉的主要回购),然后合并到我的分支,然后重新设置基础以删除无用的(对我来说:D)合并提交和树拆分 这个工作流程中让我烦恼的一件事是:在git rebase上自动隐藏保存/弹出更改?,git,git-stash,Git,Git Stash,我的git工作流经常使用rebase。我总是获取上游更改(我分叉的主要回购),然后合并到我的分支,然后重新设置基础以删除无用的(对我来说:D)合并提交和树拆分 这个工作流程中让我烦恼的一件事是: $ git rebase upstream/master Cannot rebase: You have unstaged changes. Please commit or stash them. $ git stash Saved working directory and index state
$ git rebase upstream/master
Cannot rebase: You have unstaged changes.
Please commit or stash them.
$ git stash
Saved working directory and index state WIP on cc: abc1234 Merge remote-tracking branch 'upstream/master' into local_branch
HEAD is now at abc1234 Merge remote-tracking branch 'upstream/master' into local_branch
$ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Applying: awesome code change
$ git stash pop
这里我们有4个命令,1=失败的重新设置基,2=隐藏,3=重新设置基,4=隐藏弹出。3以外的任何东西都是无意识的工作
所以,问题是:最推荐的自动化方法是什么?每次运行git stash/rebase/pop的别名?某个git配置强制重新基址隐藏或将其视为另一个提交,然后重新应用?还有什么吗?编辑:从Git版本1.8.4开始,但在Git版本2.0.1中修复了一个重要的错误,
Git rebase
现在有了--autostash
。您可以将git-rebase
配置为默认使用--autostash
,使用git-config--global-rebase.autostash-true
。请注意以下句子:
然而,小心使用:最后的藏匿
成功重设基础后的应用程序可能会导致不平凡的错误
冲突
(我还是更愿意做出承诺。)
TL;DR回答:只需进行提交(然后稍后取消提交)
它可能会帮助您认识到,git stash
实际上只是git commit
(以更复杂的形式,首先提交索引,然后提交工作树。当您应用stash时,您可以保持索引和工作树的分离,或者将它们合并为工作树更改)
隐藏的特殊之处在于,它所做的两次提交,或者使用-u
或-a
,甚至三次提交都是以一种不寻常的形式进行的(作为合并提交,它不是真正的合并),并且不放在任何分支上(相反,特殊的引用/stash
引用用于保留和查找它们)
由于它们不在分支上,rebase
不会触及它们,并且在您的工作流中,git stash pop
会将工作树更改带入新的工作树中。但是,如果您在一个分支上进行自己的(正常)提交,并重新设置基础并包含该提交,则此正常提交将与其他任何提交一起重新设置基础。我们一会儿再讨论最后一个问题;现在,让我们把它画出来,作为一系列做(或不做)重定基础的提交:
... do some work ...
... make some commits ...
... more work ...
... do something that causes upstream/master to update, such as git fetch upstream
$ git stash
在这一点上,以下是您所拥有的:
... - o - * - A - B - C <-- HEAD=master
\ |\
\ i-w <-- stash
\
@-@-@ <-- upstream/master
现在,您可以使用git stash pop
,它可以在工作树更改时恢复i/w内容,擦除stash
标签(更准确地说,弹出它,以便stash@{1}
,如果它存在,现在就是stash
,依此类推)。这释放了对原始A-B-C
链的最后引用,意味着我们也不需要i-w
位,这让我们可以将其重新绘制为更简单的:
... - @ <-- upstream/master
\
A'-B'-C' <-- HEAD=master plus work tree changes
现在,您可以git-rebase-upstream/master
,它通过D
复制A
,将它们放在最后一个@
的末尾,您可以得到:
... - o-*-@-@-@ <-- upstream/master
\
A'-B'-C'-D' <-- HEAD=master
下面是它的样子:
... - o-*-@-@-@ <-- upstream/master
\
A'-B'-C' <-- HEAD=master
\
D' [abandoned]
如果A
、B
和C
是完美的,并且是提交*
(来自其他人或早期发布的内容)的最终提交,请执行以下操作:
... - * - a1 - a2 - b1 - a3 - b2 - a4 - b3 - c1 - b4 - c2 - c3
当a1
是对A
的初步尝试时,a2
修复了a1
中的一个bug,b1
是对b
工作的初步尝试,a3
是因为意识到b1
要求A
毕竟是不同的,b2
修复了b1
中的bug,a4
修复了a3
更改为a2
的错误,b3
是b1
应该做的;然后,c1
是对C
的初步尝试,b4
是对b1
的另一种修复,c2
是一种细化,依此类推
比如说,在c3
之后,您认为它已经基本就绪。现在您运行git rebase-i origin/master
或其他任何程序,将拾取的行无序排列,使a1
到a4
有序排列,b1
到b4
有序排列,c1
到c3
有序排列,然后让rebase运行。然后修复所有冲突并确保内容仍然正确,然后运行另一个git-rebase-i
将所有四个a
版本折叠为a
,依此类推
当您完成所有操作后,看起来您第一次创建了一个完美的a
(或者使用a4
,或者其他一些操作,具体取决于您保留了哪些提交,删除了哪些提交,以及您是否在内容中重新设置了时间戳)。其他人可能不希望或不需要看到您的中间工作,尽管您可以保留它,而不是合并提交(如果有用的话)。同时,您永远不需要有未提交的东西,您必须重新设置基础,因为您只需要提交部分内容
在一行提交文本中指定这些提交名称确实有帮助,这将指导您以后的重设基础工作:
git提交-m'temp提交:启用frabulator的工作,未完成'
诸如此类。您可以使用一个名为的外部工具,它完全按照您对所有分支所说的做。这也将帮助您保持一个干净的历史图表
我已经用了好几年了,它工作得很好,特别是如果你不是git专家的话。如果您添加了自动重定基址功能,您应该知道如何正确地从失败的重定基址恢复(继续,中止,…)
安装
打开shell并运行:
sudo gem install git-up
配置
打开全局配置文件(~/.gitconfig
),并添加以下内容:
[git-up "fetch"]
all = true # up all branches at once, default false
prune = true # prune deleted remote branches, default false
[git-up "rebase"]
# recreate merges while rebasing, default: unset
arguments = --preserve-merges
# uncomment the following to show changed commit on rebase
# log-hook = "git --no-pager log --oneline --color --decorate $1..$2"
git stash
git fetch --all
[foreach branch]
git rebase --preserve-merges <branch> <remote>/<branch>
git merge --ff-only <branch>
[end foreach]
git checkout <prev_branch>
git stash pop
有关更多选项,请参阅
调用
如果所有配置都很好,只需运行:
git up
这(大致)相当于执行以下操作:
[git-up "fetch"]
all = true # up all branches at once, default false
prune = true # prune deleted remote branches, default false
[git-up "rebase"]
# recreate merges while rebasing, default: unset
arguments = --preserve-merges
# uncomment the following to show changed commit on rebase
# log-hook = "git --no-pager log --oneline --color --decorate $1..$2"
git stash
git fetch --all
[foreach branch]
git rebase --preserve-merges <branch> <remote>/<branch>
git merge --ff-only <branch>
[end foreach]
git checkout <prev_branch>
git stash pop
git隐藏
git fetch——全部
[foreach分行]
git rebase--保留合并/
git合并--仅限ff
[结束foreach]
git签出
吉特隐藏流行音乐
git stash
git fetch --all
[foreach branch]
git rebase --preserve-merges <branch> <remote>/<branch>
git merge --ff-only <branch>
[end foreach]
git checkout <prev_branch>
git stash pop
git pull --rebase --autostash [...]