Git保姆级教程(二)

一、Push & Pull

1.1 Git fetch

注:o/masterorigin/master

Git 远程仓库相当的操作实际可以归纳为两点:向远程仓库传输数据以及从远程仓库获取数据。既然我们能与远程仓库同步,那么就可以分享任何能被 Git 管理的更新(因此可以分享代码、文件、想法、情书等等)。

本节课我们将学习如何从远程仓库获取数据 —— 命令如其名,它就是 git fetch

在解释 git fetch 前,我们先看看实例。这里我们有一个远程仓库, 它有两个我们本地仓库中没有的提交。

image.png

使用git fetch后, C2,C3 被下载到了本地仓库,同时远程分支 o/master 也被更新,反映到了这一变化:

image.png

git fetch 完成了仅有的但是很重要的两步:

  • 从远程仓库下载本地仓库中缺失的提交记录
  • 更新远程分支指针(如 oirgin/master)

git fetch 并不会改变你本地仓库的状态。它不会更新你的 master 分支,也不会修改你磁盘上的文件。

理解这一点很重要,因为许多开发人员误以为执行了 git fetch 以后,他们本地仓库就与远程仓库同步了。它可能已经将进行这一操作所需的所有数据都下载了下来,但是并没有修改你本地的文件。我们在后面的课程中将会讲解能完成该操作的命令 😀

1.2 Git pull

既然我们已经知道了如何用 git fetch 获取远程的数据, 现在我们学习如何将这些变化更新到我们的工作当中。

其实有很多方法的 —— 当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支。也就是说就是你可以执行以下命令:

  • git cherry-pick origin/master
  • git rebase origin/master
  • git merge origin/master
  • 等等

实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令来完成这两个操作。它就是 git pull

git pull === git fetch + git merge

1.3 Git push

git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。它的默认值取决于你正使用的 Git 的版本,但是在教程中我们使用的是 upstream。 这没什么太大的影响,但是在你的项目中进行推送之前,最好检查一下这个配置。

让我们来模拟一下,下图左边是本地分支,右边是远程分支

image.png

使用git push后:

image.png

1.4 常见的Git工作流一

现在我们已经知道了如何从其它地方 pull 提交记录,以及如何 push 我们自己的变更。看起来似乎没什么难度,但是为何还会让人们如此困惑呢?困难来自于远程库提交历史的偏离。在讨论这个问题的细节前,我们先来看一个例子……

假设你周一克隆了一个仓库,然后开始研发某个新功能。到周五时,你新功能开发测试完毕,可以发布了。但是 —— 天啊!你的同事这周写了一堆代码,还改了许多你的功能中使用的 API,这些变动会导致你新开发的功能变得不可用。但是他们已经将那些提交推送到远程仓库了,因此你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了。

这种情况下, git push 就不知道该如何操作了。如果你执行 git push,Git 应该让远程仓库回到星期一那天的状态吗?还是直接在新代码的基础上添加你的代码,异或由于你的提交已经过时而直接忽略你的提交?

因为这情况(历史偏离)有许多的不确定性,Git 是不会允许你 push 变更的。实际上它会强制你先合并远程最新的代码,然后才能分享你的工作。

下图所示不可使用git push

image.png

那该如何解决这个问题呢?很简单,你需要做的就是使你的工作基于最新的远程分支。有许多方法做到这一点呢,不过最直接的方法就是通过 rebase 调整你的工作。咱们继续,看看怎么 rebase

git fetch
git rebase origin/master
// 上面两步等同于
git pull --rebase origin/master

git push
复制代码

得到的结果如下:

image.png

当然,除了rebase,你当然还可以使用merge,同样以上面的例子为例:

git fetch
git merge origin/master
// 上面两步等同于
git pull origin/master

git push
复制代码

得到的结果如下:

image.png

1.5 rebase 还是 merge?

在开发社区里,有许多关于 merge 与 rebase 的讨论。以下是关于 rebase 的优缺点:

  • 优点: Rebase 使你的提交树变得很干净, 所有的提交都在一条线上

  • 缺点: Rebase 修改了提交树的历史

比如, 提交 C1 可以被 rebase 到 C3 之后。这看起来 C1 中的工作是在 C3 之后进行的,但实际上是在 C3 之前。

一些开发人员喜欢保留提交历史,因此更偏爱 merge。而其他人可能更喜欢干净的提交树,于是偏爱 rebase。仁者见仁,智者见智。 😀

1.6 常见的Git工作流二

下面是一个更加复杂的例子,如何将图一转化为图二?

image.png

image.png

解决步骤如下:

git checkout master
git pull --rebase
git checkout side1
git rebase master
git checkout side2
git rebase side1
git checkout side3
git rebase side2
git checkout master
git rebase side3
git push
复制代码

看起来步骤有点多,不要慌,其实我们有更简单的写法:

git fetch
git rebase origin/master side1
git rebase side1 side2
git rebase side2 side3
git rebase side3 master
git push
复制代码

当然,我们也可以使用merge,不过最终得到的提交时间线是完全不同的喔:

git checkout master
git pull
git merge side1
git merge side2
git merge side3
git push
复制代码

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享