为什么git pull提供了合并的机会,而git push没有';T

为什么git pull提供了合并的机会,而git push没有';T,git,Git,(我下面描述的都是在本地git回购中进行的实验,不涉及远程回购。) 我创建了两个本地分支lb1和lb2。它们从同一个提交节点开始 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 Switche

(我下面描述的都是在本地git回购中进行的实验,不涉及远程回购。)

我创建了两个本地分支
lb1
lb2
。它们从同一个提交节点开始

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.
然后我通过对每一个进行不同的更改使它们分开。如下图所示:

我目前在
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
给了我一个合并的机会

合并后,我可以将
lb1
推送到
lb2

$ git push . lb1:lb2
Total 0 (delta 0), reused 0 (delta 0)
To .
   cdd1247..2dfb555  lb1 -> lb2
修订图如下所示:

并且
lb2
的更改被添加到
lb1
的日志历史记录中:

总结如下:

  • lb1—推-->lb2:失败

  • lb1我认为@dunni在评论中一针见血(即将钉子合并到板中),他们提到了一个
    git pull
    实际上是两个不同操作的方便符号。我想从你问题的断言中挑战的是,
    git pull
    git push
    是对称的。更准确的说法是,
    git fetch
    git push
    对称。当然,正如你所说,在英语中,推和拉实际上是对立的;然而,这并不一定意味着它们在其他领域的使用是对称的

    至于为什么git的实现者决定让
    pull
    尝试自动合并,我只能推测。我的理论是,因为工作回购有跟踪分支的概念,所以自动将远程跟踪分支合并到本地分支以执行拉操作是有意义的。这是因为您必须执行合并/快进操作,才能在非分离头部状态下使用更新。存储库必须保持这种分离,以便了解远程提交的内容与本地提交的内容。然而,远程的裸存储库没有跟踪分支的概念:它只是在后端运行
    git-receive-pack
    时更新其引用。它不关心引用了什么提交;这就是强制推送(
    gitpush-f
    )存在的原因。事实上,强制推送甚至不是git pack协议中的一个构造,而只是一个客户端选项,用于忽略保持历史完整性的常规检查。推送时,并不意味着需要合并/快进:只意味着更新远程对象数据库及其引用列表。在客户端,只需更新远程跟踪分支以匹配成功推送的内容(无论是否强制)


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

    我认为@dunni在评论中一针见血(即将钉子合并到板中),他们提到了一个
    git pull
    实际上是两个不同操作的方便符号。我想从你问题的断言中挑战的是,
    git pull
    git push
    是对称的。更准确的说法是,
    git fetch
    git push
    对称。当然,正如你所说,在英语中,推和拉实际上是对立的;然而,这并不一定意味着它们在其他领域的使用是对称的

    至于为什么git的实现者决定让
    pull
    尝试自动合并,我只能推测。我的理论是,因为工作回购有跟踪分支的概念,所以自动将远程跟踪分支合并到本地分支以执行拉操作是有意义的。这是因为您必须执行合并/快进操作,才能在非分离头部状态下使用更新。存储库必须保持这种分离,以便了解远程提交的内容与本地提交的内容。然而,远程的裸存储库没有跟踪分支的概念:它只是在后端运行
    git-receive-pack
    时更新其引用。它不关心引用了什么提交;这就是强制推送(
    gitpush-f
    )存在的原因。事实上,强制推送甚至不是git pack协议中的一个构造,而只是一个客户端选项,用于忽略保持历史完整性的常规检查。推送时,并不意味着需要合并/快进:只意味着更新远程对象数据库及其引用列表。在客户端,只需更新远程跟踪分支以匹配成功推送的内容(无论是否强制)


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

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

    如果git push正在合并,这个自动合并的提交将立即变成p
    $ 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 push . lb1:lb2
    Total 0 (delta 0), reused 0 (delta 0)
    To .
       cdd1247..2dfb555  lb1 -> lb2