【问题标题】:Understanding git pull --rebase [duplicate]了解 git pull --rebase [重复]
【发布时间】:2019-01-31 15:43:57
【问题描述】:

我了解到git pull --rebase origin master = git fetch origin master + git rebase origin/master。我正在使用 git 2.18

但是当我阅读 this blog 时,它说并非总是如此。

(如果我理解错了,请从这里纠正我)

博客给出了一个例子来展示git pull --rebase 的不同行为,否则我们都知道。

他说,

假设你的出发点是这样的:

a---b---c---d---e (origin/foo) (also your local "foo")

时间过去了,你已经在你自己的“foo”之上做了一些提交:

a---b---c---d---e---p---q---r (foo)

与此同时,出于反社会的愤怒,上游维护者不仅 > 重新定义了他的“foo”,甚至还使用了一两个壁球。他的提交链现在看起来像这样:

a---b+c---d+e---f (origin/foo)

此时会导致 git pull 在混乱中。即使是git fetch; git rebase origin/foo 也不会删减它, 因为在一侧提交“b”和“c”,在一侧提交“b+c” 其他,会冲突。 (与 d、e 和 d+e 类似)。

git pull --rebase 在这种情况下所做的是:

git fetch origin git rebase --onto origin/foo e foo

这给了你:

a---b+c---d+e---f---p---q---r (foo)

你可能仍然会遇到冲突,但是 它们将是真正的冲突(在 p/q/r 和 a/b+c/d+e/f 之间),并且 不是 b/c 与 b+c 冲突等引起的冲突。

我对此有以下疑问:

a) “此时 git pull 会导致混乱。” - 为什么?由于 pull 默认是非快进的,所以执行 git fetch 后状态不会变成这样。哪里乱了?

a---b---c---d---e---p---q---r (foo)
 \
  b+c---d+e---f  (origin/foo)

b) 如果 a) 为真,git rebase origin/foo 将轻松将图形转换为:

a
 \
  b+c---d+e---f  (origin/foo)
               \ 
                b---c---d---e---p---q---r (foo)

我哪里错了?为什么他说git fetch origin git rebase --onto origin/foo e foo会被处决?

【问题讨论】:

  • 作为结束评论,我将得出结论:git pull --rebase origin master = git fetch origin master + git rebase --onto origin/master $fork-point HEAD。这个$fork-point 由 git pull 代码提供给 rebase

标签: git


【解决方案1】:

关于 (a) 你是正确的,但你的结论 (b) 是错误的。

git rebase 确实试图构建您在 (b) 中描述的历史。但是想想当b 已经是上游b+c 的一部分时,它们会是什么样子。如果幸运的话,Git 会注意到它们并警告变更集现在是空的。但在更典型的情况下,bb+c 冲突。提交cde 的情况相同。

在(一系列乏味的冲突解决方案的最后),您会发现所有bcde 根本不应该参与rebase,并且你可以继续生产部分。最后,你得到了你真正想要的历史:

a
 \
  b+c---d+e---f  (origin/foo)
               \ 
                p---q---r (foo)

git pull --rebase 将您从这个混乱中解救出来,因为它知道您的 pqr 是您想要变基的唯一提交。在幕后,它使用git merge-base --fork-point 找出e 是上游提交,即不属于您的分支。

【讨论】:

  • 我检查了这种 rebase 删除冗余提交的行为,如果它们被压扁。就像这里因为 b+c 而没有采用 b,c。但结果告诉我,在提交压缩的情况下, git rebase 命令不会这样做。你也检查过一次吗?
  • 是的,我经常看到这种情况。 git rebase 无法自动删除 b,因为它的更改与上游的任何更改都不完全相同。但有时 Git 仍然可以应用更改:如果更改 b 完全独立于所有 cf,那么 Git 很可能会应用 b 并注意到它们已经被应用。 git rebase 将停止并报告类似提交现在为空。但在实践中并不经常发生。
  • 注意:git pull --rebasegit rebase 何时以及是否使用分叉点代码有点棘手。假设 Git 2.18 有帮助,因为这消除了很多“好吧,如果你的 Git 是 X 到 Y 版本,它的行为方式是这样,但是从 Y 到 Z,它的行为方式是另一种方式......”
  • @torek 我在我的 git 2.18 中检查了这种行为,它类似于作者所说的。我不知道git pull --rebase 如何使用分叉点或实际上是什么分叉点。如果可能的话,请为我们所有人发布一个深入的答案。但是,我知道 git pull 是什么以及 git rebase 的基本概念。
  • @BreakingBenjamin:查看stackoverflow.com/search?q=%5Bgit%5D+fork-point的输出
猜你喜欢
  • 1970-01-01
  • 2018-08-02
  • 2013-08-21
  • 2021-11-17
  • 2017-12-07
  • 2021-08-16
  • 2021-10-14
  • 2013-03-14
  • 2014-02-17
相关资源
最近更新 更多