如果我使用 git 拉(合并)并将我的提交压缩到 master 中会发生什么?

What happens if I use git pull (merge) and squash my commit into master?

我不确定此策略是否给我们带来了超出其价值的问题。让我们以此为例(来自 git 文档)。


    A---B---C---D---E origin/master
        \     
         X---Y--- feature/branch

我在提交 B 处创建了一个 feature/branch of origin/master。我在本地提交了 X 和 Y。 C、D 和 E 已被其他开发人员承诺为 origin。然后我使用 git pull origin master 将最新的更改从 master 拉到我的 feature/branch.

    A---B---C---D---E origin/master
        \            \
         X---Y--------M feature/branch

这似乎采用 CDE 并在我的功能分支 M 中创建一个合并提交。然后我压缩我的功能分支创建提交 Z 并将其推送到原点。

    A---B---C---D---E       origin/master
        \            \     /
         X---Y--------M---Z feature/branch

我可能误解了 pull merge

origin 现在是否包含 A、B、C 两次?

我们应该改用 rebase 吗?

非常感谢任何建议。

注意:为了这个答案的目的,我们假设你有一个名为 master 的本地分支,相当于 origin/master,还有另一个本地分支名为 feature 的分支相当于 feature/branch.

我认为您的问题是因为您的第三张图不正确。鉴于你的第二张图:

    A---B---C---D---E (master)
        \            \
         X---Y--------M (feature)

如果您随后希望将 feature 压缩到 master 上,则生成的图形将是:

A---B---C---D---E---Z (master)

在这种情况下,提交 Z 将包含来自提交 XY 的所有更改,如果合并中有任何更改,还包含 M提交。

如果您选择将 feature 变基到 master 而不是合并(在您的情况下使用 pull),图表将如下所示:

A---B---C---D---E (master)---X'---Y' (feature)

其中 X'Y' 代表 XY 的重写提交。如果您随后将这两个提交压缩为一个,您将处于与压缩合并相同的位置。 (然后您将 feature 合并到 master 以使 master 保持最新。)

Does origin now contain A,B,C twice?

假设您将 master 推到 origin,在这两种情况下,origin (master) 现在都不会包含 A、B、C 两次。

话虽这么说,也许您在概念上是倒退的,因为看起来您的图形实际上试图将 master 压缩到 feature 上。如果你这样做了,因为 master 已经合并到 feature,后续的压缩合并将没有效果,这意味着 Z 甚至不会被创建。但是,如果你先 master 合并到 feature,然后再将 master 合并到 feature,也许你会得到更接近你的想法,因为图表看起来像这样:


    A---B---C---D---E (master)
        \     
         X---Y---Z (feature)

现在 Z 将包含您提议的 CDE 的更改。然后将其合并回 master 看起来像这样:

    A---B---C---D---E---M (master)
        \              /
         X---Y--------Z (feature)

在那种情况下,Z 是一个您不需要的无意义的提交,本质上,3 次提交的 changes 有两次。 (类似于当您挑选提交到其他分支然后稍后将它们合并回来时。)

最后一个问题:

Should we use rebase instead?

如果您比较的是合并、变基和压缩,它部分归结为您希望图形看起来像什么,但也许更重要的是您希望长期保留哪些信息:

  1. Squash 的信息保留量最少。它将仅包含更改。它不保留有关作者、日期、开发人员期望的提交顺序和内容或开发开始时的原始分支点的任何信息。
  2. Rebase 保留有关作者、日期和开发人员期望的提交顺序和内容的信息,但不保留开发开始时的原始分支点。
  3. Merge 保留开发开始时的作者、日期和原始分支点的信息,但通常没有开发者期望的提交顺序和内容,而是保留提交发生时的 实际 顺序和内容。

你选择哪一个是品味问题。对于 feature branches 我个人更喜欢 rebase 选项,但前提是开发人员实际创建有意义的提交,为他们自己提供价值,并且共享一个功能分支的多个开发人员愿意交流强制推送并正确重置他们的分支机构。如果功能分支开发不符合该标准,我更喜欢壁球。对于 长期存在的共享分支 ,例如 Git Flow,我更喜欢合并(以及 --no-ff)。我永远不会 rebase 一个长期存在的共享分支。