在 git 中,在拉取后编辑历史预拉取提交会导致与原点的分歧

发布于 2024-10-04 03:51:52 字数 805 浏览 0 评论 0原文

在以下场景中:

  1. 进行提交 A、B、C
  2. 拉取、获取提交 D、E
  3. 进行更多提交 F、G、H...
  4. 意识到您需要
  5. 使用 git rebase -i 调整 B 调整 B code> 和 git commit --amend

现在 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)

In the following scenario:

  1. Make commits A, B, C
  2. Pull, getting commits D, E
  3. Make more commits F, G, H, ...
  4. Realize that you need to tweak B
  5. Tweak B using git rebase -i and git commit --amend

Now git status says:

Your branch and 'origin/master' have diverged.

How should I fix this?

Note: I did not push; this has nothing to do with pushing.

Note: Simply pulling again does not fix the problem; it just re-merges the commits D, E on top of what I already have (despite the D, E already being there in the history), which also has the side-effect of producing superfluous conflicts.

To elaborate, one answer below suggests that the history now is:

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

This isn't quite right - it's actually:

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

Hence, my problem. I'd like it to be:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我纯我任性 2024-10-11 03:51:52

我猜测您没有使用 git rebase 的 -p 选项,这意味着您所做的合并提交 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,因此取决于整个祖先链。这就是为什么在重新调整基础之后,我对所有内容都加上了“prime”。即使你没有修改C的内容,提交也会被修改。 (另一种可能性是,您保留了合并并推送,应该可以推断为最后两张图片的组合。)

I'm guessing that you didn't use the -p option to git rebase, which means that the pull you did, merging commits D and E, was wiped away. If that's all that's happened, this is simple: just pull again. If this is what happened, your history will look like this:

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

There's your divergence!

If you did preserve the merge, then quite possibly this is just because something new was pushed to origin in the meantime:

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

and so the solution, again, would be to pull.

If, however, you pushed something containing the original commit B, then you shouldn't have rebased. This will always cause divergence, and it's not a fun kind. Your history would look like this:

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

It's a fundamental fact of git's design that the SHA1 of a commit depends on the SHA1 of its parent, and therefore on the entire ancestry chain. This is why after the rebases, I've put a "prime" on everything. Even if you haven't modified C's content, the commit is modified. (The other possibility, that you preserved the merge, and pushed, should ve inferrable as a combination of the last two pictures.)

沧桑㈠ 2024-10-11 03:51:52

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

我摆脱困境的方式并不优雅:

# 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

Note: I won't accept my own answer for a while because I'm genuinely curious about other (better) approaches.

The way I got out of this was hardly elegant:

# 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文