【问题标题】:Git pull results in extraneous "Merge branch" messages in commit logGit pull 导致提交日志中出现无关的“合并分支”消息
【发布时间】:2012-01-20 12:25:27
【问题描述】:

我正在与另一个开发人员合作开发一个项目,我们使用 Github 作为我们的远程存储库。我在 Mac 上使用 git 1.7.7.3,他在 Windows 上使用 git 1.7.6。

这就是正在发生的事情

  1. 我们中的一个人(我们称他为开发人员 A,但不管是谁)将一组提交推送到 GitHub。
  2. 另一个(开发者 B)进行了一些本地提交。
  3. B 做了一个git pull
  4. B 做了一个git push
  5. 查看提交历史日志,我看到 Merge branch 'master' of github.com:foo/bar

随着时间的推移,提交日志中充斥着“合并分支”消息,并且还显示开发人员 B 正在提交开发人员 A 所做的更改。我们发现防止此问题的唯一方法是在第 3 步执行git pull --rebase,但我不知道变基会带来什么副作用。这是我第一次处理多开发人员 git 存储库,这只是正常行为吗?关于如何解决此问题的任何想法?

【问题讨论】:

  • git log --no-merges不合并即可查看日志

标签: git github commit


【解决方案1】:

解决方案:

如果其他开发人员已在远程提交,那么您需要在提交之前采取git pull。如果您这样做,您将永远不会在提交中收到无关的“合并分支”消息。

如果您在接受git pull 之前提交,那么您需要接受git pull --rebase,这样您就不会在提交中收到无关的“合并分支”消息。

另外,了解这些事情:

  1. git pull --rebase这里发生了什么? Git 会回退(撤消)你所有的本地提交,拉下远程提交,然后在新拉的远程提交之上重放你的本地提交。

  2. 这就是当您将无关的“合并分支”提交与您的提交一起推送时提交图的外观。

  1. 而且,当您在提交之前使用 git pull 或在提交后使用 git pull --rebase 时,提交图的外观就是这样。

注意:

  1. 您在案例和分支结构中所做的提交数量的差异。

  2. 此外,所有这些都发生在同一个分支上,分支与自身合并。

【讨论】:

    【解决方案2】:

    这个答案已经修改,因为我的理解、图表和结论都不正确。


    git pull 导致合并提交,因为 git 正在合并。这可以通过将分支设置为使用变基而不是合并来更改。在拉取时使用 rebase 而不是合并为共享存储库提供了更线性的历史记录。另一方面,合并提交显示了分支上的并行开发工作。

    例如,两个人在同一个分支上工作。分支开始为:

    ...->C1
    

    第一个人完成工作并推到分支:

    ...->C1->C2
    

    第二个人完成了他们的工作并想要推送,但因为他们需要更新而不能。第二个人的本地存储库如下所示:

    ...->C1->C3
    

    如果将拉取设置为合并,则第二个人存储库将如下所示。

    ...->C1->C3->M1
          \      /
           ->C2->
    

    其中 M1 是合并提交。这个新的分支历史将被推送到 repo。相反,如果将 pull 设置为 rebase,则本地 repo 将如下所示:

    ...->C1->C2->C3
    

    没有合并提交。历史变得更加线性。

    这两种选择都反映了分支的历史。 git 允许您选择您喜欢的历史记录。

    确实有一些地方 rebase 会导致远程分支出现问题。这不是其中一种情况。我们更喜欢使用 rebase,因为它简化了已经很复杂的分支历史,并显示了相对于共享存储库的历史版本。

    您可以设置 branch.autosetuprebase=always 让 git 自动将您的远程分支建立为 rebase 而不是 master。

    git config --global branch.autosetuprebase always
    

    这个设置会导致 git 自动为每个远程分支创建一个配置设置:

    branch.<branchname>.rebase=true
    

    您可以为已设置的远程分支自行设置。

    git config branch.<branchname>.rebase true
    

    我要感谢 @LaurensHolst 质疑和追查我之前的陈述。我当然已经了解了更多关于 git 如何处理拉取和合并提交的信息。

    有关合并提交的更多信息,您可以阅读ProGit-Book 中的Contributing to a ProjectPrivate Small Team 部分显示合并提交。

    【讨论】:

    • “在拉取时使用 rebase 而不是合并可为共享存储库提供正确的历史记录。使用合并提供了错误的历史记录。” ——支持这个相当大胆的声明的理由是什么?合并的历史不可能是“虚假历史”。它准确地描述了事情发生的顺序。你通过变基所做的实际上是改变历史,创建一个稍微线性化的版本。你为了美观牺牲了准确性。也许你更喜欢做一些事情,但绝不是更真实的事情。
    • 使用 rebase 代替 merge 不会为了美观而牺牲准确性。我们使用 --no-ff 进行合并,因此美观不是要求。准确是一种愿望。 Rebase 提供了这种准确性。
    • 如何重新设置历史记录更准确?你没有澄清这一点,我不明白它会如何。
    • 历史记录反映了提交在 shared 存储库中发生的时间。第一天,共享仓库看到提交 C2。在第 2 天,共享存储库看到提交 C3。如果 C3 在 C2 之前出现,那么时间的反映将不正确。 C3 没有出现在 C2 之前。 rebase 所做的只是重新组织 local 存储库上的提交,以正确反映共享存储库显示的历史记录。
    • 您的问题让我重新审视了我对合并提交的理解。我的图表不正确。我正在修改讨论。我的结论也是错误的。变基和合并的历史同样正确。你可以做出自己的选择。
    【解决方案3】:

    实际上有一个更简单的答案。只需让开发人员 B 在提交之前进行拉动。这将阻止这些合并提交,因为它们是由您在本地存储库中创建的历史记录引起的,本地提交尝试与远程存储库上的提交历史记录合并。如果您在执行拉取操作时收到一条消息,说“更改将被覆盖”,这只是意味着你们都触摸了同一个文件,所以这样做:

    git stash
    git pull
    git stash pop
    

    那么您可以解决任何合并冲突(如果有)。

    【讨论】:

    • 最烦人最焦虑的就是合并冲突。我宁愿避免它
    • @Green 如果您担心合并冲突,那么即使 git pull 也不例外。
    • 除了在pull之前忘记stash的时候。呃 git 要求我始终处于游戏的顶端。
    • 不管怎样,都需要git pull --rebase在本地之前集成远程更改。
    【解决方案4】:

    你可以这样做:

    git pull --rebase
    

    但是,这将始终将您的更改置于协作者之上。但是您不会收到任何污染合并消息。

    【讨论】:

      【解决方案5】:

      您看到的提交非常好。 pull 有效地运行 git fetch 然后 git merge 所以当你运行 git pull 时通常会发生合并。

      使用变基而不是合并的替代方法是可能的,但通常你应该避免它。变基允许您保留线性历史记录,但也删除有关最初发生的分支的任何信息。它还将导致当前分支的历史被重写,重新创建不包含在目标分支中的所有提交(在您的情况下,远程)。由于重新创建的提交是不同的 提交,因此在与他人一起开发时,这可能会导致很多混乱,尤其是当人们在重写之前已经检查了这些提交的一部分时(例如使用功能分支)。因此,根据经验,您应该永远重写任何已经推送的提交。

      您看到的提交是为了组合两个(或更多)分支。在合并多个分支之后,提交什么都不做是完全没问题的。事实上,当您在查看历史记录时有一个合并分支的合并提交时,它会非常清楚。与变基相比,合并还可以让您有效地查看开发时的原始历史,包括共存的实际分支。

      所以,长话短说:是的,合并提交完全没问题,您不必担心它们。

      【讨论】:

      • 很好的答案。我自己尝试了 rebase 风格,因为它在一些开源项目贡献指南中被推荐,它给我带来了问题。团队中的一个新成员也有同样的情况。我认为 rebase 选项不适用于整天一起工作的团队,但对于具有主要贡献者和其他仅提交补丁的贡献者的项目是正确的。这些应该可以很好地获取主仓库并在发出拉取请求之前重新调整他们的更改。
      • @sTodorov 如果没有新的更改,那么 pull 的 fetch-part 将什么都不做,但合并仍在执行。因此,如果您当前的本地分支不是最新的,它会将新的更改合并到您的分支中。如果它不能进行快进合并(如果你有不同的提交),那么它将创建一个合并提交。
      • 这个答案看起来像使用 OP 所描述的 rebase 是危险的,但事实并非如此。第 3 步的变基不会重写整个历史记录。只有尚未推送的本地提交会被重新应用到新 HEAD 之上(推送到该分支的最新提交)。这可以防止无关的合并提交并且没有其他副作用。
      • @bobesponja 所有不在拉取的远程分支上的提交都将被重写。这可以包括来自其他分支的已发布提交,例如具有其他人之前可能已经访问过的功能分支。因此,是的,在不考虑你的 rebase 的情况下 rebase 有点危险。
      • @bobesponja 是的,如果你提前发布了你的特性分支(因为其他人正在处理它,或者只是作为备份),那么你不应该重新设置它,因为其他人可能已经获取了它。然后,正如您自己所说的那样,重新设置基准与我在回答中所述的重新设置准则背道而驰。但是,如果您不发布您的提交,那么如果您愿意并且不介意线性历史,那么变基就可以了。但这取决于你的工作方式,所以一般的答案是避免它,除非它真的很安全。顺便提一句。我修改了我的答案,所以如果问题得到解决,如果你删除你的反对票,我将不胜感激。
      【解决方案6】:

      执行 git pull 将插入“合并分支”消息,这就是它的作用。通过执行 git pull,您已将远程分支合并到本地分支。

      当您执行 git pull 并且存在冲突时,git 日志将显示冲突文件的更新来自解决冲突的用户。我认为这是因为解决冲突的人重新提交了文件。

      据我所知,这就是 git 的工作方式,并且没有办法绕过它。

      变基会清除 git 历史记录,因此您将无法看到合并发生的时间。

      【讨论】:

        猜你喜欢
        • 2012-12-15
        • 2019-07-14
        • 2013-02-07
        • 2021-06-26
        • 1970-01-01
        • 2011-11-06
        • 2017-03-05
        • 2015-10-19
        • 2013-01-12
        相关资源
        最近更新 更多