代码之家  ›  专栏  ›  技术社区  ›  Benjol

从多个Git钢筋中恢复“旧提交”

  •  5
  • Benjol  · 技术社区  · 14 年前

    我知道 this 问题,但不确定如何将其映射到我的当前情况。(REBASE是可怕的,松开REBASE是双重恐怖!)

    我从我的主人的几个不同的功能分支开始:

    master    x-x-x-x-x-x-x-x-x-x
                 \       \    \
    FeatureA      1-2-3   \    \
    FeatureB               A-B  \
    FeatureC                     X-Y-Z
    

    我想把它们全部合并在一起,检查它们是否工作,然后再合并到主控形状的顶部,所以我做了一个:

    git checkout FeatureB
    git rebase FeatureA
    git mergetool //etc
    git rebase --continue
    

    然后

    git checkout FeatureC
    git rebase FeatureB
    git mergetool //hack hack
    git rebase --continue
    

    这让我

    master    x-x-x-x-x-x-x-x-x-x
                 \
    FeatureA      1-2-3 
                       \
    FeatureB            A'-B'
                             \ 
    FeatureC                  X'-Y'-Z'
    

    然后我纠正了一些未正确编译的位,并将整个特性设置为可接受的状态:

    master    x-x-x-x-x-x-x-x-x-x
                 \
    FeatureA      1-2-3 
                       \
    FeatureB            A'-B'
                             \ 
    FeatureC                  X'-Y'-Z'-W
    

    我的问题是,我的同事告诉我,我们还没有准备好吃羽绒服。

    有没有什么方法可以让我保留所有的工作,同时又回到一个我可以将FeatureC重新设置为FeatureB的情况?

    3 回复  |  直到 14 年前
        1
  •  5
  •   Cascabel    14 年前

    这是我对答案的理解,基于评论:

    当您执行REBASE时,当前分支上的提交是“撤消”,然后是“重新应用”,但实际上,它们不是撤消的,它们是“记住的”*,并用新的ID重新应用,例如,如果我查找 git reflog show FeatureB ,我得到如下信息:

    7832f89 FeatureB@{0} rebase finished: refs/heads/FeatureB onto f4df3
    efd3fed FeatureB@{1} commit: B
    f3f3d43 FeatureB@{2} commit: A
    2f32fed FeatureB@{3} branch: Created from HEAD
    

    正如@jefromi所说,原件仍然存在(reflog中的a和b提交的shas与git日志中的shas不同,后者对应于a'和b')。

    同样地, git reflog show FeatureC 看起来像这样

    32873ef FeatureC@{0} commit: W
    17dafb3 FeatureC@{1} rebase finished: refs/heads/FeatureC onto 89289fe
    893eb78 FeatureC@{2} commit: Z
    a78b873 FeatureC@{3} commit: Y
    e78b873 FeatureC@{4} commit: X
    378cbe3 FeatureC@{5} branch: Created from HEAD
    

    同样,原始的z、y和x提交仍然存在

    所以,我的问题的解决方案是创建一个新的分支 FeaturesBC 从master的头部(例如),然后cherry选择提交功能b 2&1,然后选择功能c 4、3、2,和(可能)w:

    git checkout master
    git checkout -b FeaturesBC
    git cherry-pick f3f3d43 
    git cherry-pick efd3fed 
    //etc...
    

    (这似乎奏效了,我不得不重新进行一些相同的合并,但并不太糟糕)

    编辑,来自Jefromi:

    可能不需要采摘樱桃。您还可以简单地重新创建分支,其中分支位于钢筋之前:

    git branch FeatureB-old efd3fed
    git branch FeatureC-old 893eb78
    

    或者,如果您想放弃FeatureB和FeatureC的重新调整位置,返回到它们之前的位置:

    git branch -f FeatureB efd3fed
    git branch -f FeatureC 893eb78
    

    最后,请注意,如果您愿意,可以使用reflogs中提供的其他符号-例如, FeatureC@{2} 而不是 893eb78 . 这意味着“FeatureC的第二个先前位置”。但是,在查看reflog之后,请注意只能立即使用它,因为一旦您再次更新分支(移动它,提交到它…), FutuRc@ { 2 } 将改为17DAFB3。

    正如@jefromi对我的问题的评论:

    您可能已经在master或featurec(称为featuresabc)上创建了一个新的分支,并将每个分支合并到其中,使功能分支保持完整。有利于保持各功能分支的独立历史。

    *准确地说,旧的提交对象只剩下在存储库中。它们最终将被删减,因为您不希望回购充满旧的悬而未决的承诺;这将是第一次发生。 git gc 运行并且提交至少两周(由配置 gc.pruneExpire )

        2
  •  1
  •   Tobias Kienzler    14 年前

    如果所有其他失败,您可以从主服务器重新启动 git cherry-pick 所有的B或C承诺重新创建这些分支。如果这是唯一的解决方案,我希望别人已经写了一个脚本…

        3
  •  1
  •   knittl    14 年前

    你可以使用 git rebase --onto <old-merge-base from B> A C 把从C到A的所有东西重新排列到主控形状上的一个点上。它会给你留下:

    master    x-x-x-x-x-x-x-x-x-x
                 \       \
    FeatureA      1-2-3   \
                           \
    FeatureB                A'-B'
                                \ 
    FeatureC                     X'-Y'-Z'-W
    

    要找到要重新定位的点,可以使用git的reflog和 git merge-base _

    master    x-x-x-x-x-x-x-x-x-x
                |\ 
    FeatureA    | 1-2-3
                 \
    FeatureB       A'-B'
                        \ 
    FeatureC             X'-Y'-Z'-W
    

    ( git rebase --onto $(git merge-base A master) A C )