在git中,在pull之后编辑历史预拉提交会导致从原点发散

时间:2010-11-20 00:26:27

标签: git rebase

在以下情形中:

  1. 提交A,B,C
  2. 拉,提交D,E
  3. 提交更多提交F,G,H,......
  4. 意识到你需要调整B
  5. 使用git rebase -igit commit --amend
  6. 调整B

    现在git status说:

    Your branch and 'origin/master' have diverged.
    

    我该如何解决这个问题?

    注意:我没有推;这与推动无关。

    注意:再次拉动并不能解决问题;它只是重新合并了我已经拥有的提交D,E(尽管D,E已经存在于历史中),这也产生了产生多余冲突的副作用。

    详细说明,下面的一个答案表明现在的历史是:

    - A - B' - C' - F' - G' - H' (master)
    \
     D - E (origin/master)
    

    这不太对 - 实际上是:

    - A - B' - C' - D(?) - E(?) - F' - G' - H' (master)
    \
     D - E (origin/master)
    

    因此,我的问题。我希望它是:

    - A - B' - C' - F' - G' - H' (master)
    \         /
     D - E (origin/master)
    

2 个答案:

答案 0 :(得分:1)

我猜你没有使用-p选项来git rebase,这意味着你所做的拉动,合并提交D和E,被抹去了。如果发生了这一切,这很简单:再拉一次。如果发生这种情况,您的历史将如下所示:

- A - B' - C' - F' - G' - H' (master)
\
 D - E (origin/master)

你的分歧!

如果确实保留了合并,那很可能这只是因为在此期间新的内容被推送到原点:

- A - B' - C' - X' - F' - G' - H' (master)
\              /
 D - E -------- - Z (origin/master)

所以解决方案同样是拉动。

但是,如果你推送了包含原始提交B的内容,那么你就不应该重新定位。这将始终引起分歧,并不是一种有趣的类型。您的历史记录如下:

    B' - C' - F' - G' - H' (master)
   /
- A - B - C - X - F - G - H (origin/master)
\            /
 D - E ------

git设计的一个基本事实是提交的SHA1取决于其父级的SHA1,因此取决于整个祖先链。这就是为什么在重新定位之后,我对所有事情都进行了“巅峰”。即使您尚未修改C的内容,也会修改提交。 (另一种可能性,你保留合并,并推,应该可以推断为最后两张图片的组合。)

答案 1 :(得分:0)

注意:我暂时不会接受自己的答案,因为我对其他(更好)的方法非常好奇。

我摆脱这种方式并不优雅:

# stash F, G, H - can't simply reorder them before D, E since they depend a lot on D, E
for i in {1..3}; do git reset HEAD^; git stash; done
# wipe out the weird non-merge D and E commits
git reset --hard HEAD~2
# pull to merge D, E again
git pull
# restore F, G, H
for i in {1..3}; do git stash pop; git commit -a; done