本文参考于:http://www.zhanglian2010.cn/2014/07/git-pull-vs-fetch-and-merge/

使用git fetch和git pull都可以更新远程仓库的代码到本地,但是它们之间还是有区别

git fetch

git fetch origin master
git log -p master..origin/master
git merge origin/master
  1. 从远程的origin仓库的master主分支更新最新的版本到origin/master分支上
  2. 比较本地的master分支和origin/master分支的差别
  3. 合并内容到本地master分支

git pull

git pull origin master

相当于git fetch 和 git merge,即更新远程仓库的代码到本地仓库,然后将内容合并到当前分支。

所以,简单的说git pull相当于git fetch后再做一个git merge。那么它们具体的区别如何分析呢,这就需要我们再认识下git了,先看看下面这张图:

我们知道,git其实有好几个区,工作区(workspace)、暂存区(index)、本地仓库(local repository),当然还有远程仓库(remote repository)。远程仓库为我们保存一份代码拷贝,如github,而工作区、暂存区和本地仓库都在本地,这就是为什么没有网络我们也照样使用git提交(commit)代码更新,因为提交仅是提交到本地仓库,待有网络之后可以再推送(push)到远程仓库。

正如上图所示,git fetch是将远程仓库的更新获取到本地仓库,不影响其他区域。而git pull则是一次性将远程仓库的代码更新到工作区(同时也会更新本地仓库)。

通常来说,git fetch和merge与git pull的区别已经很明显了,但是如果想再了解下git是如何操作的,则需要我们了解下分支这个git的强大特性(分支的概念确实太牛逼了,我不确定我的理解是否是正确的)。

分支

分支(branches)是用来标记特定的代码提交,每一个分支通过SHA1sum值来标识,所以对分支进行的操作是轻量级的——你改变的仅仅是SHA1sum值。所以为什么git提倡大家多使用分支,因为它即轻量级又灵活。简单的说,分支有两种:

本地分支(local branches)” ,当你输入“git branch”时显示的:

1
2
$ git branch
  * master

远程分支(remote branches)” ,当你输入“git branch -r”是显示的:

1
2
$ git branch -r
  origin/master

如果你对分支在本地是如何存储感兴趣的话,看看项目中的下面文件,文件里面存的就是一个SHA1sum值:

  • .git/refs/head/[本地分支]
  • .git/refs/remotes/[正在跟踪的分支]

我们来看看远程分支,Pro Git这本书描述的非常好。远程分支(remote branch)是对远程仓库中的分支的索引。它们是一些无法移动的本地分支;只有在 Git 进行网络交互时才会更新。远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支的位置。

我们用 (远程仓库名)/(分支名) 这样的形式表示远程分支。比如我们想看看上次同 origin 仓库通讯时 master 分支的样子,就应该查看 origin/master 分支。如果你和同伴一起修复某个问题,但他们先推送了一个 iss53 分支到远程仓库,虽然你可能也有一个本地的 iss53 分支,但指向服务器上最新更新的却应该是 origin/iss53 分支。

下面我把Pro Git中的例子摘抄过来。假设你们团队有个地址为 git.ourcompany.com 的 Git 服务器。如果你从这里克隆,Git 会自动为你将此远程仓库命名为 origin,并下载其中所有的数据,建立一个指向它的 master 分支的指针,在本地命名为 origin/master,但你无法在本地更改其数据。接着,Git 建立一个属于你自己的本地 master 分支,始于 origin 上 master 分支相同的位置,你可以就此开始工作:

这样,我们在本地仓库的本地分支和远程分支都有了,并且起始于同一位置。

如果你在本地 master 分支做了些改动(在本地工作区commit了代码到本地仓库),与此同时,其他人向 git.ourcompany.com 推送了他们的更新,那么服务器上的 master 分支就会向前推进,而与此同时,你在本地的提交历史正朝向不同方向发展。不过只要你不和服务器通讯,你的 origin/master 指针仍然保持原位不会移动:

注意这里的本地分支已经前移,而远程分支还保持不动,而远程仓库的master其实也已经前移,所以可以说本地的远程分支origin/master是过时的。

可以运行 git fetch origin 来同步远程服务器上的数据到本地。该命令首先找到 origin 是哪个服务器(本例为 git.ourcompany.com),从上面获取你尚未拥有的数据,更新你本地的数据库(仓库),然后把 origin/master 的指针移到它最新的位置上:

现在大家能看到git fetch的作用了吗?

接下来还没完,我们来看看git的高级玩儿法。为了演示拥有多个远程分支(在不同的远程服务器上)的项目是如何工作的,我们假设你还有另一个仅供你的敏捷开发小组使用的内部服务器 git.team1.ourcompany.com。可以用第二章中提到的 git remote add 命令把它加为当前项目的远程分支之一。我们把它命名为 teamone,以便代替完整的 Git URL 以方便使用:

注意这里是多个远程分支,不同的远程服务器。

现在你可以用 git fetch teamone 来获取小组服务器上你还没有的数据了。由于当前该服务器上的内容是你 origin 服务器上的子集,Git 不会下载任何数据,而只是简单地创建一个名为 teamone/master 的远程分支,指向 teamone 服务器上 master 分支所在的提交对象 31b8e:

由此你在本地就有了两个远程分支,作为指向两个远程服务器上 master 分支的索引。

好了,不扯远了,总结下git fetch和git pull:

  • git fetch is the command that says “bring my local copy of the remote repository up to date.”
  • git pull says “bring the changes in the remote repository where I keep my own code.”

由于git pull把过程的细节都隐藏了起来,以至于你不用去了解git中各种类型分支的区别和使用方法。当然,多数时候这是没问题的,但一旦代码有问题,你很难找到出错的地方。看起来git pull的用法会使你吃惊,简单看一下git的使用文档应该就能说服你。
将下载(fetch)和合并(merge)放到一个命令里的另外一个弊端是,你的本地工作目录在未经确认的情况下就会被远程分支更新。

单独进行下载和合并是一个好的做法,你可以先看看区别(diff),然后再决定是否和本地代码合并。而且分开来做,可以清晰的区别开本地分支和远程分支,方便选择使用。所以尽量少用git pull,多用git fetch和merge

参考:

http://www.oschina.net/translate/git-fetch-and-merge?cmp

http://stackoverflow.com/questions/292357/difference-between-git-pull-and-git-fetch

http://git-scm.com/book/zh/Git-%E5%88%86%E6%94%AF-%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF

Git中pull对比fetch和merge的更多相关文章

  1. git 的 pull、fetch、merge

    1.pull = fetch + merge In the simplest terms, git pull does a git fetch followed by a git merge. You ...

  2. Git 少用 Pull 多用 Fetch 和 Merge

    本文有点长而且有点乱,但就像Mark Twain Blaise Pascal的笑话里说的那样:我没有时间让它更短些.在Git的邮件列表里有很多关于本文的讨论,我会尽量把其中相关的观点列在下面. 我最常 ...

  3. 【转】Git 少用 Pull 多用 Fetch 和 Merge

    原文网址:http://www.cnblogs.com/flying_bat/p/3408634.html 本文有点长而且有点乱,但就像Mark Twain Blaise Pascal的笑话里说的那样 ...

  4. Git 少用 Pull 多用 Fetch 和 Merge(转)

    英文原文:git: fetch and merge, don’t pull This is too long and rambling, but to steal a joke from Mark T ...

  5. Git 少用 Pull 多用 Fetch 和 Merge 【已翻译100%】【转】

    本文转载自:https://www.oschina.net/translate/git-fetch-and-merge?lang=chs&page=1# 本文有点长而且有点乱,但就像Mark ...

  6. Git 中 pull 和 clone 的区别

    git pull git clone clone 是本地没有 repository 时,将远程 repository 整个下载过来. pull 是本地有 repository 时,将远程 reposi ...

  7. Idea中解决Git中pull代码内容冲突

    Git开发中,由于项目开发人员不只一个,所以在代码开发中,多个开发人员可能会对同一文件同一地方的代码进行修改,这样在先后提交到master上时,就会产生冲突,以下是演示冲突产生和解决冲突的示例: 1. ...

  8. git无法pull仓库refusing to merge unrelated histories

    本文讲的是把git在最新2.9.2,合并pull两个不同的项目,出现的问题如何去解决fatal: refusing to merge unrelated histories 我在Github新建一个仓 ...

  9. git无法pull仓库refusing to merge unrelated histories (拒绝合并不相关仓库)

    原文地址 https://blog.csdn.net/lindexi_gd/article/details/52554159 本文讲的是把git在最新2.9.2,合并pull两个不同的项目,出现的问题 ...

随机推荐

  1. JavaScript电子时钟+倒计时

    JavaScript时间类      获取时分秒:          getHours()          getMinutes();          getSeconds();       获取 ...

  2. xampp 80端口被占用解决办法

    很多朋友安装xampp之后,启用服务器或者数据库失败,发现端口已经被占用.因为每台电脑占用端口的软件不一样,要如何解决这个问题. 第一种解决方法: 检查软件安装路径中是否有中文,如下图: 解决方法: ...

  3. ps 文字处理篇

    ps文字处理篇 1.对文字镂空处理并且移除到新图像上: 首先创建图层-文字编辑-横排编辑 其次 魔棒工具选择通过颜色来选择选区 右击图层-栅格化图层 删除键将选择的颜色删除留下选区- 复制粘贴到另一个 ...

  4. websevice中runtime modeler error: Wrapper class com.ws.jaxws.Add is not found问题的解决办法

    查询了网上的资料,有以下解决办法: 1> 先用apt命令将主程序进行编译,然后生成一些java文件2> 升级JDK到版本jdk1.6u17或以后 这两种办法我没有试过,但是试了以下这种方法 ...

  5. C++11新特性——初始化列表 initializer_list

    破事水: 由于最近数据结构有个实验报告说是要对字符串进行排序,想偷个懒不想一个一个地赋值,虽然可以用strcpy和传入二级指针的形式直接写,但是这样感觉不美观漂亮. 然后就去膜了一下C++11的新特性 ...

  6. 总结-jQuery

    一.ajax提交,如果某个变量的值填的是doc对象,jQuery不报错,也没有反应,如: {userName : $('#userName')}.正确的写法 {userName : $('#userN ...

  7. linux实践之ELF文件分析

    linux实践之ELF文件分析 下面开始elf文件的分析. 我们首先编写一个简单的C代码. 编译链接生成可执行文件. 首先,查看scn15elf.o文件的详细信息. 以16进制形式查看scn15elf ...

  8. jQuery 取选中的radio的值方法

    var val=$('input:radio[name="sex"]:checked').val(); 附三种方法都可以: $('input:radio:checked').val ...

  9. 从PowerDesigner表字段的Name到EF实体类属性的Display Name(根据PowerDesigner生成EF实体类中文注释和验证元数据)

    第一步:将PowerDesigner表字段的中文Name填入Comment中:工具-Execute Commands-Edit/Run Script... '********************* ...

  10. IOS 调用系统照相机和相册

    /** *  调用照相机 */ - (void)openCamera { UIImagePickerController *picker = [[UIImagePickerController all ...