Git中pull对比fetch和merge

本文参考于: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

时间: 2024-08-06 07:54:09

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

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

英文原文:git: fetch and merge, don’t pull This is too long and rambling, but to steal a joke from Mark Twain Blaise Pascal I haven’t had time to make it shorter yet.  There is some discussion of this post on the git mailing list, but much of it is tangen

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

This is too long and rambling, but to steal a joke from Mark Twain Blaise Pascal I haven’t had time to make it shorter yet.  There is some discussion of this post on the git mailing list, but much of it is tangential to the points I’m trying to make

git无法pull仓库refusing to merge unrelated histories

http://blog.csdn.net/lindexi_gd/article/details/52554159 本文讲的是把Git在最新2.9.2,合并pull两个不同的项目,出现的问题如何去解决fatal: refusing to merge unrelated histories 我在Github新建一个仓库,写了License,然后把本地一个写了很久仓库上传. 先pull,因为两个仓库不同,发现refusing to merge unrelated histories,无法pull 因为

IDEA从Github中pull Maven项目后要解决的问题

很多人在开发中都会碰到的一个问题,当我们用IDEA从Github中检出Maven工程后(Java),发现既不能运行,也不能编译,左侧的树形目录还怪怪的,现在就来说说如何解决这个问题.1.生成SSH Key:dos命令窗口中执行:ssh-keygen -t rsa -C "[email protected]", 后面的 [email protected] 改为你在 github 上注册的邮箱,之后会要求确认路径和输入密码,我们这使用默认的一路回车就行.成功的话会在用户目录下(如C:\Us

三十一、Git中的fetch和pull

Git中从远程的分支获取最新的版本到本地有这样2个命令: 1. git fetch:相当于是从远程获取最新版本到本地,不会自动merge     git fetch origin master git log -p master..origin/master git merge origin/master 以上命令的含义:   首先从远程的origin的master主分支下载最新的版本到origin/master分支上   然后比较本地的master分支和origin/master分支的差别  

使用Git中的Merge与Rebase与开源项目同步代码

基于开源项目的开发有两种主要工作模式.模式1是在从开源项目中拉出一个分支,在这个分支中开发新feature,完成后合并到upstream中.适用于本身是开源项目的developer.模式2是从开源项目中拉出分支后独立发展,但定期从upstream拉更新(如重要版本升级时).无论是哪种,都会面临本地分支与upstream同步代码的问题.为此,git主要提供了两种方式:一种是merge, 一种是rebase.下面通过例子简单过一下它们的基本流程. 假设开源项目的git地址为git://xxx.org

Git 使用心得: fetch, merge, remote

最近做project,用到了Git,因此写下来以便总结. git clone, add 和commit 什么的就不说了... 主要说说远程端仓库的事. 首先,先得到远程库上master分支的东西: git fetch origin master origin是远程仓库默认名,如果在 remote add 的时候自己重新取了远程仓库名,那就用自己取的名字:master 则是远程分支名. 这时候只是相当于从远程库拷了代码到本地,还没有和本地的merge,这就是为什么不直接pull,因为先fetch再

Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase

上篇博客聊了<git分支管理之rebase 以及 cherry-pick相关操作>本篇博客我们就以Learning Git中的关卡进行展开.下方列举了LearningGit中的 merge.rebase.reset.revert.cherry-pick 以及交互式rebase相关关卡的操作以及对应的解析.后边在聊交互式rebase操作是,不单单给出了LearningGit中的内容,而且给出了真正的Git分支在交互式rebase操作时的具体案例. learngitbranching的地址为:ht

Git中的merge命令实现和工作方式

想象一下有如下情形:代码库中存在两个分支,并且每个分支都进行了修改,最后你想要将其中的一个分支合并到其他的分支中.个人博客网址 http://swinghu.github.com/ 那么要问合并的处理过程是怎么样的呢?Git是对每个分支,依据分支的历史数据按照序列化操作,还是它只是合并每个分支里文件的最后版本?这是一个问题,我想对git的merge操作有必要进行分析一下. 回忆一下,我们知道Git的版本库内部结构是以有向无环图(directed acyclic graph)组织起来的:每一次co