从origin拉取时,"git pull"命令之间的区别是什么?

91

这些命令之间有何不同?

# 1
git pull
# 2
git pull origin
# 3
git pull origin master
# 4
git pull origin/master
# 5
git pull origin HEAD:master

即使阅读了手册,有时也不清楚究竟发生了什么。例如:如果没有配置上游,git pull 的含义是什么?(手册仅指默认为配置的上游。) - michas
简而言之:
  1. 如果没有当前分支的配置,将会失败,否则就像2.一样带有远程名称。
  2. 将使用给定远程的默认获取配置(并合并第一个),而在3.中,您可以指定要获取和合并的内容。
  3. 在我看来是无效的。
  4. (如果它有效),将把远程HEAD放入refs/remotes/origin/master并进行合并。
- andi5
2
投票重新开放此问题,因为不幸的是,它是site:stackoverflow.com git Difference "git pull" "git pull origin master"的搜索结果之一。 - user456814
2个回答

90

git pull是一个方便的命令,同时执行不同的操作。基本上它只是git fetchgit merge(或git rebase)这两个命令的组合,前者连接到远程存储库并获取新提交,后者将新提交合并到您的本地分支中。由于涉及两个不同的命令,git pull的含义并不总是显而易见。

您可以为本地分支配置上游分支。在克隆后,您将拥有一个本地分支“master”,一个远程分支“origin”,并且您的主分支具有“origin/master”作为上游分支。我假设以下是这种设置。(您可以使用git branch -vv或查看 .git/config 来查看上游配置。)

现在回答您的问题:

  1. git pull = git fetch origin + git merge origin/master(或任何您的上游分支)
  2. git pull origin = git pull(只要 origin 是您的上游远程分支)
  3. git pull origin master = git fetch origin master + git merge FETCH_HEAD
  4. git pull origin/master:无效,除非您有一个名为“origin/master”的远程
  5. git pull origin HEAD:master:尝试直接将本地 master 重置为 origin 上 HEAD 指向的任何内容。(不要这样做。)

2
执行 git pull origin HEAD:master 为什么是个坏主意? - Ryan Edwards
2
右侧应该是一个远程分支。请查看手册中的警告。如果您使用此功能,请确保知道自己在做什么。 - michas
如果我在另一个分支上,执行 git pull 命令会拉取该分支还是主分支? - aWebDeveloper
1
@aWebDeveloper:为了完整起见:git pull origin HEAD:master 本质上(在 Git 2.6 中的脚本重写之前是字面意思)将 HEAD:master 部分传递给 git fetch,因此它执行了 git fetch 步骤所做的操作;然后使用 git fetch 步骤获取的提交哈希值进行合并或变基。 Refspecs 是 source:dest,因此将 HEAD 给其他 Git 进行翻译。所以这取决于另一个 Git,但通常另一个 Git 的 HEAD 是其 master 的名称。如果您不在自己的 master 上,则合并或变基会使用已更新的 master (dest)(除非 fetch 失败)。 - torek
1
还有一件需要注意的事情:永远不要执行 git pull origin br1 br2。它看起来和感觉就像是应该执行 git checkout br1; git pull origin; git checkout br2; git pull origin ——但实际上并不是这样!相反,它实际上执行的是:git fetch origin && git merge origin/br1 origin/br2,将两个获取结果合并到你当前的分支中,Git 称之为章鱼合并。这绝不是任何人想要的。可能 git pull 应该完全拒绝这个命令(真正想要它的人可以先运行 fetch,然后再运行 merge)。 - torek
显示剩余3条评论

19

pull 基本上是一个 fetch(从远程仓库获取一些提交和相关对象到你的仓库),然后是将它们 "应用" 到你的工作副本的操作。默认情况下,第二阶段使用 merge 完成,但你可以设置 pull.rebase 变量为 true,这样它就会使用变基代替。

pull 命令引发两个问题:第一个是,精确地获取了什么?第二个是,如何将这些更改应用到我的工作副本中?让我们从第一个问题开始。命令的完整形式为

git pull [options] [repository] [<refspec>...]

options 是标志,用于控制行为(例如,--rebase 使 pull 的工作方式成为一个 fetch + rebase,即使 pull.rebasefalse)。

repository 是要从中获取的远程仓库的名称(或 URL)。

refspecs 是一种简洁的方式来指定您想要从远程获取哪些引用以及您想将它们放置在当前工作副本的何处。

首先让我们看最明确的形式。

 git pull origin branch1:branch2
这基本上是在说,拉取远程名为origin的引用branch1中的更改,然后将它们合并(或变基)到本地分支branch2中。例如,如果我运行git pull origin master:dev,我将得到一个名为dev的本地分支,该分支将指向与master相同的提交。有关如何指定refspec的详细信息,请参见此处。您可以使用*表示多个refspecs。例如,git pull origin refs/heads/*:refs/heads/*将从远程存储库中拉取所有分支(存储在heads下),并将它们合并到具有相同名称的本地分支中。
现在,让我们逐个删除参数以讨论默认情况。首先,我们可以从refspec中删除目标,并简单地说git pull origin branch1。这将首先将远程分支branch1 fetch到您的本地存储库中。它将作为临时引用称为FETCH_HEAD。之后,它将运行git merge FETCH_HEAD,这将把此分支合并到当前活动分支(即HEAD)中。当您在本地分支中并想从远程获取更改时,通常会执行此操作。
现在,让我们完全删除branch1,只需说git pull origin。现在,git知道从哪里获取(origin),但不知道要获取什么。它有一些默认值。大多数情况是,如果您的配置文件具有branch.<name>.merge选项(这是一个类似于[branch "master"]的部分内部称为merge的条目),它将使用refspecs进行操作。
如果我们完全删除origin,只需说git pull,它将检查配置文件以查看是否有一个branch.<name>.remote,该选项指定要从哪个远程获取。加上上述内容就可以告诉您要拉取什么了。
您提到的第4和第5点不是正常的用例。第一个只有在有一个名为origin/master的远程引用时才有意义,但这很少见。 origin/master通常是跟踪远程origin上的master分支的本地引用。第二个将尝试在远程上获取HEAD中的更改(通常是master),然后将其合并到本地的master中。虽然这可能是您想经常执行的操作,但该命令相当不寻常,而且我很少见到人使用它。
我省略了一些细节,但这些应该足以让您在日常工作中保持安全和舒适。有关所有详细信息,请查看git pull的手册页面。

如果我举个例子,说git pull origin master:dev,那么我会得到一个名为dev的本地分支,它将指向与master相同的提交。所以你会下载一个名为dev的新分支,并且它会指向master? - user33276346
不,你会从远程获取“master”分支,但本地将其称为“dev”。 - Noufal Ibrahim
“git pull origin refs/heads/*:refs/heads/” 对我没用,我得到了“no matches found: refs/heads/:refs/heads/”。我还尝试了“git pull origin refs/remotes/origin/:refs/heads/*”,但也不起作用。我认为在一个命令中拉取远程所有分支以及将这些分支合并/变基到相应的本地分支是不可能的。 - Ben Butterworth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接