2017-07-13 30 views
1

(我在下面所描述的本地git仓库的实验都发生了什么。无远程回购参与。)为什么git pull提供了合并的机会,但git push没有?

我创建2个地方分支机构lb1lb2。它们从相同的提交节点开始。

git branch lb1 
git branch lb2 

我让它们相互上游。如下:

$ git checkout lb2 
Switched to branch 'lb2' 

$ git branch -u lb1 
Branch lb2 set up to track local branch lb1. 

$ git checkout lb1 
Switched to branch 'lb1' 

$ git branch -u lb2 
Branch lb1 set up to track local branch lb2. 

然后我通过对它们进行不同的改变使它们发散。如下图所示:

enter image description here

$ git branch -vv 
* lb1 6774aa6 [lb2: ahead 1, behind 1] lb1 change 
    lb2 cdd1247 [lb1: ahead 1, behind 1] lb2 change 

我目前lb1。然后我试图一个分支(LB1)推到其他(LB2),看看会发生什么:

$ git push . lb1:lb2 
To . 
! [rejected]  lb1 -> lb2 (non-fast-forward) 
error: failed to push some refs to '.' 
hint: Updates were rejected because a pushed branch tip is behind its remote 
hint: counterpart. Check out this branch and integrate the remote changes 
hint: (e.g. 'git pull ...') before pushing again. 
hint: See the 'Note about fast-forwards' in 'git push --help' for details. 

所以,如果我的理解是正确的,它说,推分支的顶端lb1)的背后是其远程对方lb2)。我必须先结帐lb1并从lb2拉到整合lb2的变化。

所以我这样做:(请注意,我在lb1分支现在)

$ git pull 
From . 
* branch   lb2  -> FETCH_HEAD 
Auto-merging file1.txt 
CONFLICT (content): Merge conflict in file1.txt 
Automatic merge failed; fix conflicts and then commit the result. 

所以git pull使我有机会合并。

后,我合并,我可以推lb1lb2

$ git push . lb1:lb2 
Total 0 (delta 0), reused 0 (delta 0) 
To . 
    cdd1247..2dfb555 lb1 -> lb2 

和版本图是这样的:

enter image description here

而且lb2的变化是加入lb1的日志历史:

enter image description here

总结:

  • LB1 - 推 - > LB2:失败
  • LB1 < - 拉 - LB2:有机会合并

我的问题是:

为什么git push不提供合并的机会?从英语的角度来看,我认为pushpull是对称的。所以我期望他们有同样的结果。

+0

一个失败的推动意味着分支不是快进,你会重写一些历史记录(或重新编入死亡历史记录) –

+1

git pull是git fetch和git merge命令的组合。这就是它提供合并的原因。 git push是一个独立的命令。 – dunni

+0

@AnthonySottile通过“分支”,我猜你是指推送的目标分支,在我的场景中为'lb2'。 – smwikipedia

回答

4

我认为@dunni在评论中指出头部(即钉入钉板)时,他们提到git pull实际上是两种不同操作的便利标记。我想挑战你的问题的断言是git-pull是对称的git-push。指出git-fetchgit-push对称可能更准确。当然,正如你所说的,英语的推拉是非常对立的,然而,这并不一定意味着在其他领域的使用上是对称的。

至于为什么git的实现者决定尝试一个automerge,我只能推测。我的理论是,因为工作回购有跟踪分支这样的概念,所以自动合并远程跟踪分支到本地分支来执行pull操作是有意义的。这是因为您必须执行合并/快进才能使用处于未分离HEAD状态的更新。存储库必须保持这种分离状态,以便知道遥控器提供的内容与本地提供的内容。然而,远程仓库没有跟踪分支这样的概念:它只是在后台运行git-receive-pack时更新它的参考。它并不在乎提交什么提交;这就是为什么力推(git push -f)存在。实际上,力推并不是git-pack-protocol中的构造,而只是一个客户端选项,可以忽略保持历史记录完整性的正常检查。推送时,并不意味着需要合并/快进:您只暗示远程及其参考列表上的对象数据库的更新。在客户端,只需更新远程跟踪分支以匹配您成功推送的内容(无论是否强制)。

总结:获取需要合并,因为获取的远程跟踪分支必须合并到相应的本地分支中供您在工作存储库中使用。然而,推动你可能不一定需要合并;你只是更新远程分支。

+1

Upvote for“merge the nail into the board” –

1

你可能应该更好地在git maiilist中提问,但有一个重要的区别:由pull执行的合并仍然是你的个人历史的一部分。您可以测试它,或者更新合并信息,或者改变主意并重置为在合并之前提交。你可以花时间解决冲突。

如果git push合并,这个自动合并提交会立即成为公共历史的一部分。这也会导致同步问题,以防有人在同一时间推送,合并需要解决冲突或编写提交消息。

其实,我有一个script试图实现它,但我不能说我已经看到很多关于它的反馈。现在人们习惯使用大多数个人功能分支,并且只在服务器合并请求时才合并。

相关问题