git pull
:
git pull
运行git fetch
,然后
- (不需要等待您确认!) 运行第二个Git命令。
如果你想执行两个 Git 命令,并且 git pull
将要执行的第二个命令是你想要执行的命令,那么使用 git pull
是可以的。
我个人经常喜欢在fetch
命令和其他命令之间 插入 一些 额外的 Git 命令。但当使用 git pull
时这是不可能做到的,因为它不会等待你。因此我通常避免使用 git pull
。(特别是我经常想运行git log
来看看我正在处理什么内容。)
我还发现对于新手来说,他们认为 git pull
是有点神奇的。通过使用分开的两个步骤,而不是使用 git pull
,他们学会如何使用 Git。使用 git pull
,他们就无法学习如何使用 Git。所以我鼓励新手使用分开的命令。这不仅有助于强调“Git 不是魔法”的部分,而且还有助于区分 git pull
运行的第二个命令是你自己选择的:
- 您可以选择让
git pull
运行 git merge
。
- 您可以选择让
git pull
运行 git rebase
。
这两个命令都是合并工作,但它们执行方式是非常不同的。如果您在自己的代码库中没有做任何工作,则与别人共享的工作内容是得到别人的工作,所以无论使用哪个命令都无关紧要。但是,如果您在自己的代码库中做了一些工作,则会有所不同。
当您将这两个命令分开时,其区别就更加明显了:
git merge
表示将我的工作与他们的工作合并: 将“nothing”与“something”合并=“something”;将“something”与“something else”合并=“some third thing”。
git rebase
表示在他们的工作之上重新执行我的工作: 在“something”之上重新执行“nothing”=“something”,但是在其他的情况下,您可能会看到这个效果(如果不行,请查阅关于git rebase
的相关信息)。
针对您的具体问题:
我该如何从远程更新我的本地分支?
这要看你想要哪个结果以及你对第二个命令有多确定。
据我所见,
git pull origin <my-branch>
和
git pull origin
的区别在于,后者会获取除了
<my-branch>
以外的所有分支,大多数情况下是这样。这时我们真正需要将
git pull
分解成两个步骤,并观察它给出了什么。
当你运行
git pull
时,可以提供选项。例如,以下两种调用
git pull
的方法都是有效的:
git pull --rebase
git pull --ff-only
这些选项是矛盾的,因为
--rebase
表示
git pull
应该在第二个命令中运行
git rebase
,而
--ff-only
表示
git pull
应该向第二个命令提供
--ff-only
选项,这意味着它应该运行
git merge
而不是
git rebase
。
所以,一些选项控制着
pull
应该使用哪个第二个命令。其他选项被传递
给第二个命令。还有一些选项被传递到第一个
git fetch
命令。这有点令人困惑,这也是学习
git fetch
首先的又一个原因。
您还可以提供
参数,例如您在此处建议的
<my-branch>
。您提供的所有非选项参数都将传递给
git fetch
。通过
-
或
--
标识可将参数与选项区分开来。(单横线
-
选项是单个字母,例如
-j
或
-4
;双横线
--
选项是多个字母,例如
--rebase
和
--show-forced-updates
。)
如果您提供像
origin
和
<my-branch>
这样的
参数,它们将传递给
git fetch
,并影响
git fetch
的操作方式。没有参数时,
git fetch
将:
找到正确的远程连接(通常是 origin
):一个"remote"是一个简短的名称,用来访问另一个Git软件,这里会从另一个Git仓库读取内容。在这种情况下,你想要访问GitHub、Bitbucket或GitLab等平台上的某个Git软件,它们上面有你之前创建的Git仓库所在的Git仓库。现在你想要访问相同的Git仓库,并查看它们是否有任何你的Git仓库还没有的新提交。(那些提交是如何出现的?我们稍后再担心这个问题。)
调用该软件并连接到该仓库。该仓库有它的分支和它的提交。该仓库中的分支不是你的分支!他们是他们的分支。它们可能在其中存储了不同的提交哈希值。
根据存储在其各个分支名称中的哈希ID,确定它们有哪些提交,而你没有,并决定哪些提交是你想要在你的仓库中的。
如果你在git fetch
命令中没有列出某些分支名称,则你的Git会默认更新所有分支的所有副本。因此,你的Git将检查它们的master
或main
、develop
和feature/short
或feature/long
或feature/tall
等分支。你的Git将确定它们是否有任何你没有的新提交,并将这些提交带到你的Git仓库中。
由于提交是用全局唯一标识符编号的,因此你的Git(你的运行在你的仓库上的软件)现在将拥有所有他们的提交,并使用相同的编号。你的Git还将拥有他们没有的全部自己的提交。现在,你的Git已经获得了所有他们的提交,你的Git将创建或更新所有你的远程跟踪名称:origin/main
或origin/master
代表他们的main
或master
,origin/develop
代表他们的develop
,以此类推。你的Git通过在每个他们的分支名称前添加remote名称 origin
来构建这些名称。
这些remote-tracking名称构成了你的Git对于它们的分支上次被你接收到(即获取)的位置的记忆。所以不带参数的
git fetch
会更新
所有这些远程跟踪分支,因为不带参数的
git pull
实际上是调用了不带参数的
git fetch
,所以你的所有
origin/*
名称都将得到更新。当使用一个参数时,像
git pull origin
,同样的事情会发生,只不过现在你明确地表达了你想要使用名称为
origin
的远程仓库。如果这是你唯一的远程仓库——这是一种典型的设置——那么这将完全相同;任何其他的名称,比如
git fetch belgium
或其他什么的,都将导致错误。
但是如果你运行
git fetch origin develop
,那么这告诉你的Git,对于这个
git fetch
操作,你希望你的Git访问他们的Git,查看它们的所有分支,但是
限制更新只更新你的
origin/develop
所需的提交。如果他们的
main
有一个新提交,你不会更新你的
origin/main
。(你几乎肯定希望或必须稍后这样做,所以这并没有真正为你节省多少时间。实际上,由于Git优化获取的方式,这可能会导致稍后需要更多时间,而不是一次性完成所有操作。但如果你想要,这个选项是存在的。)
由于
git pull
将
所有参数传递下去,因此
git pull origin develop
指示你的
git fetch
步骤限制其自身到名为
develop
的远程分支。(同样的操作也会更新你的
origin/develop
)
但现在第二个命令起作用了。在运行了
git fetch
之后,无论它使用了什么额外的选项和参数,你的
git pull
现在运行了你选择的第二个命令。(你确定自己选择了一个吗?总是确保你知道Git将在这里运行哪个第二个命令!大多数人都会设置一个半永久的,这样他们就知道了。)第二个命令可以是:
git rebase [options argument(s)]
或者:
git merge options argument(s)
Git 的 pull
命令 通常会在此处传递一些选项和/或参数。特别地,对于 git merge
命令,它会传递:
-m "merge branch '<branch>' of <url>"
设置合并信息,然后传递您引入的最新提交的原始哈希ID。对于rebase,它可能会传递--autostash
,也可能会传递提交哈希ID(或者可以让rebase自行找出@{upstream}
)。虽然您不需要了解所有这些内容,但值得记住的是,git pull
为git merge
功能提供了一些额外的操作,以设置合并消息。
这里还有一个最后的警告:
git pull origin br1 br2
对于新手来说,使用 不要使用 的方法是很诱人的。它运行了 git fetch origin br1 br2
然后运行一个 章鱼合并 (实际上是 HEAD
, origin/br1
和 origin/br2
的合并),除非你真的知道自己在做什么,否则你不想要一个章鱼合并。
这会导致几个底线
如果你将 git pull
设置为 始终运行 git rebase
,那么你自己运行 git fetch
然后再运行 git rebase
和只运行 git pull
没有太大区别。这是因为没有合并消息需要修改。但在执行此操作之前,请确保你知道 rebase 做了什么:rebase 比合并更加复杂。
如果你将 git pull
设置为 始终运行 git merge
,则 pull
执行的抓取-合并操作具有一定的优点 (?) ,可以将合并消息设置为比两个单独的命令得到的默认消息略微好一些。比较:
merge branch 'smörgåsbord' of ssh://github.com/swedish/meatballs.git
vs:
merge branch 'origin/smörgåsbord'
两者都没有提供任何有用的信息,但有些人可能更喜欢其中一个。
小心使用 git pull <remote> <branch1> <branch2>
,几乎肯定会出错(尽管如果你设置为rebase,这应该只会给你一个错误;在此情况下进行rebase没有意义)。
如果你想要在两个命令之间运行一个命令(例如git log
),以便选择使用哪个第二个命令,则不能使用一次完成所有操作的 git pull
。这就是我避免使用 git pull
的原因和时间。
除此之外,它们基本上是相同的东西,一旦你知道 git pull
只是为你运行两个Git命令。
git pull
在任何形式下都没有问题。你只需要了解它的作用,看它是否符合你当前的需求即可。 - Marek R