概述
既然我们已经知道了如何用 git fetch
获取远程的数据, 现在我们学习如何将这些变化更新到我们的工作当中。
其实有很多方法的 —— 当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支。也就是说就是你可以执行以下命令:
git cherry-pick o/main
git rebase o/main
git merge o/main
- 等等
实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令来完成这两个操作。它就是我们要讲的 git pull
。
即git pull
相当于git fetch
和 git merge o/main
的缩写,取回远程主机某个分支的更新,再与本地的指定分支合并。
注意点
即使当前分支有没有 commit 的变动,也可以使用git pull
从远程拉取分支。
命令
git pull完整格式
git pull <远程主机名> <远程分支名>:<本地分支名>
git pull origin next:master
如果远程分支是与当前分支合并,则冒号后面的部分可以省略。
git pull origin next
// 相当于
git fetch origin
git merge origin/next
追踪关系
在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。比如,在git clone
的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master
分支自动"追踪"origin/master
分支。
建立追踪关系,在现有分支与指定的远程分支之间
git branch --set-upstream-to=origin/[remote-branch] [branch]
如果当前分支与远程分支存在追踪关系,git pull
就可以省略远程分支名。
即本地的当前分支自动与对应的origin
主机"追踪分支"(remote-tracking branch)进行合并。
git pull origin
如果当前分支只有一个追踪分支,连远程主机名都可以省略。
即当前分支自动与唯一一个追踪分支进行合并。
git pull
参数
--rebase
如果合并需要采用rebase模式,可以使用--rebase
选项。
git pull --rebase
相当于git fetch
和 git rebase o/main
的缩写
git pull --rebase <远程主机名> <远程分支名>:<本地分支名>
-p
如果远程主机删除了某个分支,默认情况下,git pull
不会在拉取远程分支的时候,删除对应的本地分支。这是为了防止,由于其他人操作了远程主机,导致git pull
不知不觉删除了本地分支。
但是,你可以改变这个行为,加上参数 -p
就会在本地删除远程已经删除的分支。
git pull -p
// 等同于
git fetch --prune origin
git fetch -p
详解
假设你周一克隆了一个仓库,然后开始研发某个新功能。到周五时,你新功能开发测试完毕,可以发布了。但是 —— 天啊!你的同事这周写了一堆代码,还改了许多你的功能中使用的 API,这些变动会导致你新开发的功能变得不可用。但是他们已经将那些提交推送到远程仓库了,因此你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了。
这种情况下, git push
就不知道该如何操作了。如果你执行 git push
,Git 应该让远程仓库回到星期一那天的状态吗?还是直接在新代码的基础上添加你的代码,亦或由于你的提交已经过时而直接忽略你的提交?
因为这情况(历史偏离)有许多的不确定性,Git 是不会允许你 push
变更的。实际上它会强制你先合并远程最新的代码,然后才能分享你的工作。
解决方法
方式一:
git fetch
git rebase o/main
git push
我们用 git fetch
更新了本地仓库中的远程分支,然后用 rebase 将我们的工作移动到最新的提交记录下,最后再用 git push
推送到远程仓库。
方式二:
git fetch
git merge o/main
git push
我们用 git fetch
更新了本地仓库中的远程分支,然后合并了新变更到我们的本地分支(为了包含远程仓库的变更),最后我们用 git push
把工作推送到远程仓库
尽管 git merge
不会移动你的工作(它会创建新的合并提交),但是它会告诉 Git 你已经合并了远程仓库的所有变更。这是因为远程分支现在是你本地分支的祖先,也就是说你的提交已经包含了远程分支的所有变化。
方式三:
很好!但是要敲那么多命令,有没有更简单一点的?
当然 —— 前面已经介绍过 git pull
就是 fetch 和 merge 的简写,类似的 git pull --rebase
就是 fetch 和 rebase 的简写!
git pull --rebase
git push
git pull
git push