如何移动git提交进出存储?

fom*_*mil 1 git

我在一个拥有分支策略的团队中工作,有时会重写某些分支的上游提交历史记录.

能够将我的历史记录中的最后N次提交移动到存储区,然后重置HEAD,然后将这些存储条件移回我的本地历史记录,同时保留提交消息将非常有用.

如何在本地分支和存储之间移动提交?有没有办法为N次提交自动执行此操作?例如,创建可以调用类似的别名git stashHistory 5; git popHistory 5.假设当前工作目录在执行此操作时没有任何更改.

tor*_*rek 6

从技术上讲,你根本不能移动提交,而不是你的意思.而且,"stash"实际上只是一个引用名称(refs/stash).该git stash脚本使用reflog隐藏该单个名称下的多个项目.当您运行git stash save以创建一个提交时,该脚本将创建一个提交(与目前为止的每个其他提交不同)并将存储点指向它.1 我想,有可能以这种方式实现你的目标,但这是尝试它的错误方法.

幸运的是,无论如何,这不是问题.你真正想要的只是一个普通的老人git rebase!该git rebase命令只是git cherry-pick在一个git reset地方的某个地方自动执行一系列操作.

这是如何工作的.你的工作在你的分支机构上B,当你的上游团队upstream/B指向我o在这里标记的提交链(旧)时,你就开始做了:

..- * - o - o - o           <-- upstream/B
                  \
                    x - y   <-- B
Run Code Online (Sandbox Code Playgroud)

现在你的上游团队去"重写历史" upstream/B,用o新的ns 取代三个旧的(可能是4 n秒,甚至).旧的仍然存在,特别是在你的回购中,因为你B包括它们:

        n - n - n - n       <-- upstream/B
      /
..- * - o - o - o           <-- upstream/B@{1}, in reflog
                  \
                    x - y   <-- B
Run Code Online (Sandbox Code Playgroud)

我认为你想要做的是复制xy(或者你的例子中更长的5个链)到新的,稍微不同的提交,x'y'产生这个图:

                        x' - y'   <-- B
                      /
        n - n - n - n       <-- upstream/B
      /
..- * - o - o - o           <-- upstream/B@{1}, in reflog
                  \
                    x - y   <-- [reflog only]
Run Code Online (Sandbox Code Playgroud)

要做到这一点,您只需要在git rebase将分支重新分支到新的时间之后立即开始提交upstream/B@{1}(即x).Bupstream/B

$ git rebase --onto upstream/B 'upstream/B@{1}' B
Run Code Online (Sandbox Code Playgroud)

这就是我upstream/B@{1}在图形绘图中留下reflog标签的原因:在使用其中一个重写git fetch更新之后upstream/B,它就是让您x轻松找到的标签.请注意,如果upstream/B已多次更新,则reflog编号可能会增加1.(我也把...@{1}上面的单引号,以保护它免受贝壳 - 有一些 - 喜欢吃牙箍.你的机会不是,而且不需要它们.)

最新版本的git的(2.x中,虽然1.9有它,我认为)有一个新的标志选项来git merge-base--fork-point,是为了帮助自动找出其中的o-到- x过渡,即使引用日志数量不再只是1.因此,如果你有一个足够新的git,你可以完全自动化整个事情.如果没有,您可以手动计数(就像您一直在做的那样),或者手动浏览upstream/Breflog以确保@{1}是正确的后缀.在任何情况下,你需要的是找到o-到- x过渡,因为这是你必须传递给说法git rebase.

(您可能不需要的--onto说法,但它的安全包括,没有--onto混帐选择了"到"从分支的所谓的"上游",这是一个非常令人困惑的术语,尤其是因为的一个rebase论点实际上是所谓的 upstream和它意味着不同的东西!上游参数是我们正在使用的地方upstream/B@{1};它标识要从rebase cherry-pick复制过程中排除的提交.)


1实际上,它至少有两个新的提交 - 两个用于普通git stash save,三个用于添加-a-u- 和一个refs/stash参考点是合并提交.这不是人们通常认为的合并; 该脚本只是使用 - 可能会说"滥用" - 合并提交的多父提交方面能够存储这些提交并使用单个引用名称以便稍后查找所有这些提交.