0

使用以下 git 命令有什么区别

git pull origin master
git pull origin master:master

一些观察

1)第一个告诉我是否有任何冲突,但另一个只是说“拒绝 - 非快进”

2)如果失败,第二个不会更新我的远程指针,即原点/主控

4

3 回答 3

7

这有点棘手,所以让我们一次一点地处理它。

git pull像这样滚动:

  1. 从给定的远程(示例中的第一个参数)获取给定的 refs 1(示例中的第二个参数,称为refspec —“参考规范”的一个端口)。

    如果 remote 参数丢失,Git 会尝试使用branch.<name>.remote本地存储库中的配置变量来获取它,其中<name>是当前签出分支的名称。

    如果缺少 refspec 参数,Git 会尝试使用branch.<name>.merge本地存储库中的配置变量来获取它,其中<name>的含义与上述相同。

  2. 将所有获取的 ref合并到当前签出的分支,因此 @Oznerol256 不正确。

现在让我们来解释一下 refspecs 之间的区别master以及master:master何时git pull......

git pull将 refspec 直接传递给git fetch,并以下列方式解析 refspec:“从远程获取与左侧的规范匹配的所有 refs,:可能使用它们来更新本地存储库中的匹配 refs,由规范指定在“的右侧:。这里的关键是,如果:refspec 中没有,或者它的右侧没有任何内容,这将被解释为“不更新任何内容” git fetch

现在让我们深入挖掘。根据refspecs 的解释规则,裸“master”(在大多数情况下2)被解释为refs/heads/master,这意味着“名为 «master» 的分支”。

好的,现在应该清楚了git pull origin master

  1. 从由指示的远程git fetch origin master获取的调用,并且仅将获取的对象存储在数据库中(加上更新特殊的 ref )。它不会更新本地存储库中的任何分支或标签。refs/heads/masteroriginFETCH_HEAD

  2. git merge FETCH_HEAD尝试refs/heads/master将从远程存储库获取的 as 的状态合并到当前签出的分支中的调用。

    显然,这可能会导致冲突,这就是您在第一种情况下观察到的。

现在让我们更深入地挖掘。正如现在应该清楚的那样,master:masterrefspec (通常2)扩展为refs/heads/master:refs/heads/master,因此git pull origin master:master滚动如下:

  1. 它调用git fetch origin master:master哪个

    1. refs/heads/master从远程获取和
    2. refs/heads/master通过获取的对象更新本地。

      如果本地“主控”未完全包含在远程“主控”中,这可能会因“非快进”错误而失败,这就是您所观察到的。

此时没有尝试合并,因为第一步产生了错误。

应该注意的是,您的两个示例都没有正确更新本地引用:第一个示例只是不尝试此操作,而第二个示例尝试更新所谓的错误引用-正确的调用将git pull origin +refs/heads/master:refs/remotes/origin/master强制因此+)更新正确的远程分支,然后尝试将提取的内容合并到当前签出的分支中。

为了理解为什么会使用这样一个“奇怪”的 refspec,让我们看看 Git 在你调用时使用了什么 refspec——git fetch origin因为在这种情况下它会读取remote.<remotename>.fetch本地存储库中的配置变量(这个变量是由git remote addor创建的git clone):

$ git config --local --get remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*

如您所见,它告诉git fetch强制更新和更新远程分支。

现在可以看出,git pull在没有真正了解其内部运作的情况下,它经常被无意识地过度使用。在我看来,最好使用两步操作而不是拉:

  1. git fetch origin— 更新远程分支。
  2. git merge origin/master— 将上次在“origin”上看到的“master”状态合并到当前签出的分支中。

    如果将当前签出的分支设置为跟踪要合并的远程分支,则 Git 调用变得更加简单:

    git merge @{u}
    

我还建议阅读这篇文章


1 Git 用语中的“ref”是一个命名实体,它指向一个提交(简单或直接 ref)或另一个 ref(符号 ref —HEAD是符号 ref)。分支和标签是简单引用的示例,HEAD可能两者兼有:当您签出一个分支时,它是一个符号引用,当您签出其他任何内容时(因此处于“分离的 HEAD”状态),它是一个简单的引用。

2如果有一个标签和一个名为“master”的分支,则 refspec 将被解析为标签的名称——标签具有优先权。在这种情况下,可以使用完整的 ref 名称来指定分支。

于 2013-09-13T13:36:53.317 回答
0

Agit pull固有地执行两个操作:首先, a git fetch,然后是git merge

使用git pull origin mastermaster您的远程分支origin将被获取(检索),然后合并到您当前的签出分支中。

通过定义两个分支名称,您可以指定将哪个分支合并到哪个分支的refspec 。

通用示例如下:“从指定的远程检索源分支,将其与目标分支合并。

git pull <remote> <source>:<destination>

于 2013-09-13T13:37:57.003 回答
0

第一个告诉 gitmaster从远程拉取分支origin。它不会告诉 git 将获取的提交合并到哪里。它使用配置中指定的合并键。

第二个告诉 gitmaster从 remove中拉出分支origin并将其合并到本地分支master中。这会覆盖配置中的合并键。

于 2013-09-13T10:37:40.963 回答