Git pull在提交日志中导致无关的"合并分支"消息

msh*_*rir 99 git commit github

我正在与一个项目的另一个开发人员合作,我们正在使用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. 查看提交历史记录日志,我看到github.com:foo/bar的合并分支"master"

随着时间的推移,提交日志中充斥着"合并分支"消息,并且还将开发人员B显示为提交开发人员A所做的更改.我们发现防止这个问题的唯一方法就是git pull --rebase在步骤3进行,但我不知道变形引起的副作用是什么.这是我第一次使用多开发人员git仓库,这是正常行为吗?有关如何解决这个问题的任何想法?

pok*_*oke 86

你看到的提交完全没问题.一个pull有效的运行git fetch,然后git merge所以当你运行一个合并通常发生git pull.

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

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

所以,长话短说:是的,合并提交完全没问题,你不应该担心它们.

  • 这个答案使得看起来像OP所描述的那样使用rebase是危险的,但事实并非如此.在步骤3重新定位不会重写整个历史记录.只有未被推送的本地提交才会通过在新HEAD(最新提交到该分支的最新提交)之上重新应用来重写.这可以防止无关的合并提交,并且没有其他副作用. (23认同)
  • 非常好的答案.我自己尝试了rebase风格,因为它在一些开源项目贡献指南中被推荐,并且它给我带来了问题.团队中的新成员也是如此.我认为rebase选项不适用于整天一起工作的团队,但对于有主要贡献者的项目和仅提交补丁的其他贡献者来说是正确的.那些应该是很好的获取主要回购并在发出拉动请求之前重新定义他们的更改. (2认同)
  • @sTodorov如果没有新的更改,那么pull的fetch-part将不执行任何操作,但仍在执行合并.因此,如果您当前的本地分支不是最新的,它会将新更改合并到您的分支中.如果它不能进行快进合并(如果你有不同的提交),那么它将创建一个合并提交. (2认同)

Bil*_*oor 46

由于我的理解,图表和结论不正确,因此修改了这个答案.


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

例如,两个人正在同一个分支上工作.分支开头为:

...->C1
Run Code Online (Sandbox Code Playgroud)

第一个人完成他们的工作并推向分支机构:

...->C1->C2
Run Code Online (Sandbox Code Playgroud)

第二个人完成他们的工作,并希望推动,但不能因为他们需要更新.第二个人的本地存储库看起来像:

...->C1->C3
Run Code Online (Sandbox Code Playgroud)

如果将pull设置为merge,则第二个人员库将如下所示.

...->C1->C3->M1
      \      /
       ->C2->
Run Code Online (Sandbox Code Playgroud)

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

...->C1->C2->C3
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

git config --global branch.autosetuprebase always
Run Code Online (Sandbox Code Playgroud)

此设置使git自动为每个远程分支创建配置设置:

branch.<branchname>.rebase=true
Run Code Online (Sandbox Code Playgroud)

您可以自己为已设置的远程分支设置此项.

git config branch.<branchname>.rebase true
Run Code Online (Sandbox Code Playgroud)

我要感谢@LaurensHolst提出质疑并继续我之前的发言.我当然学到了更多关于git如何使用pull和merge提交的知识.

有关合并的详细信息,提交你可以阅读使用项目ProGit图书.在私人小团队部分显示合并的提交.

  • "在pull上使用rebase而不是merge,可以为共享存储库提供正确的历史记录.使用合并提供了错误的历史." - 支持这个相当大胆的陈述的理由是什么?合并的历史不可能是"虚假的历史".它准确地描述了事情发生的顺序.你通过变基所做的事实上是*改变*历史,创建一个稍微更线性的版本.你牺牲了美学的准确性.也许你喜欢做的事情,但绝不是更真实. (7认同)
  • 您的问题让我回顾了我对合并提交的理解.我的图表不正确.我正在修改讨论.我的结论也是错误的.rebase和merge的历史同样正确.你可以自己做出选择. (6认同)
  • 使用rebase而不是merge并不会牺牲美学的准确性.我们使用--no-ff进行合并,因此美学不是一种要求.准确性是一种愿望.Rebase提供了准确性. (2认同)
  • *如何*更新历史更准确?你没有澄清这一点,我不明白它会是怎样的. (2认同)
  • 历史反映了 __shared__ 存储库中发生提交的时间。第 1 天,共享存储库看到提交 C2。第 2 天,共享存储库看到提交 C3。如果 C3 在 C2 之前,那么时间的反映将不正确。C3 没有先于 C2。rebase 所做的就是重新组织 __local__ 存储库上的提交,以正确反映共享存储库显示的历史记录。 (2认同)

gab*_*ous 10

你可以做:

git pull --rebase
Run Code Online (Sandbox Code Playgroud)

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


Luk*_*uke 8

实际上有一个更简单的答案.让开发人员B在提交之前做一个拉动.这将阻止那些合并提交,因为它们是由您在本地提交的本地存储库上创建的历史记录导致的,该历史记录尝试与远程存储库上的提交历史记录合并.如果您在执行拉动时收到一条消息,说明"更改将被覆盖",则只表示您触摸了同一个文件,所以:

git stash
git pull
git stash pop
Run Code Online (Sandbox Code Playgroud)

那么你可以解决任何合并冲突,如果有的话.


kcl*_*air 7

做一个git pull会插入"Merge branch"消息,这正是它所做的.通过执行git pull,您已将远程分支合并到本地分支中.

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

据我所知,这就是git的工作方式,而且没有办法解决它.

重新定位将吹走git历史记录,因此您将无法看到合并发生的时间.