在git rebase上自动隐藏保存/弹出更改?

在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。我总是获取上游更改(我分叉的主要回购),然后合并到我的分支,然后重新设置基础以删除无用的(对我来说:D)合并提交和树拆分

这个工作流程中让我烦恼的一件事是:

$ 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 [...]