题 'git pull'和'git fetch'有什么区别?


主持人注意: 鉴于这个问题已经存在 六十四个答案 张贴到它,考虑你是否 贡献任何新东西 在发布另一个之前。

有什么区别 git pull 和 git fetch


10149
2017-11-15 09:51


起源


我发现这篇写得很好的文章关于git fetch和git pull值得阅读: longair.net/blog/2009/04/16/git-fetch-and-merge - Marcos Oliveira
我们的替代方法已经成为 git fetch; git reset --hard origin/master 作为我们工作流程的一部分它会消除局部变化,让您与主人保持同步但确保您不仅仅在当前变化的基础上进行新的更改并弄得一团糟。我们已经使用了一段时间,它在实践中基本上感觉更安全。请务必先添加/ commit / stash任何正在进行的工作! - Michael Durrant
确保您知道如何正确使用git stash。如果你问'拉'和'取'那么也许'stash'也需要解释...... - Henry Heleine
很多来自Mercurial的人继续使用“git pull”,认为它相当于“hg pull”。它不是。 Git相当于“hg pull”是“git fetch”。 - Serge Shultz
git fetch命令使用分支获取更新的代码,并且还将在本地获取新添加的分支,git pull命令仅获取当前分支的更新代码 - Kartik Patel


答案:


用最简单的话来说, git pull 做了 git fetch 接下来是 git merge

你可以做一个 git fetch 随时更新您的远程跟踪分支机构 refs/remotes/<remote>/

此操作永远不会更改您自己的本地分支 refs/heads,无需更改工作副本即可安全使用。我甚至听说有人跑步 git fetch 定期在后台的一个cron工作(虽然我不建议这样做)。

一个 git pull 您可以采取哪些措施使本地分支机构与其远程版本保持同步,同时还可以更新其他远程跟踪分支机构。

Git文档: git pull


8470
2017-11-15 09:52



“A git pull”是您为使您的存储库更新而采取的措施“< - 不是fetch已经完成的存储库更新吗?你不是说它让你的本地分支机构与远程分支机构保持同步吗?合并:它将远程分支与这些分支的本地副本合并,或者它在这里合并到底是什么? - Albert
@Albert:是的,措辞奇怪。 git pull 将永远合并到 目前的分支。因此,您选择要拉出的分支 从,它将它拉入当前分支。该 从 分支可以是本地的或远程的;它甚至可以是一个不是注册的远程分支 git remote (意思是你传递了一个URL git pull 命令行)。 - intuited
@espertus:不。推送永远不会自动进行合并。期望用户在本地解决任何合并冲突, 然后 推回遥控器。 - Greg Hewgill
如果我在 /home/alice/ 并做 git fetch /home/bob,我应该将哪些参数传递给后续的 git merge ? - ripper234
学习Git的人注意事项: pull 实际上不能被a模仿 fetch 再加上一个 merge。我刚刚获取了一个只有远程分支指针发生变化的变化 merge 拒绝做任何事情。 pull另一方面,快速转发我的跟踪分支。 - Roman Starkov


  • 当你使用 pull,Git会尝试自动为您完成工作。 它是上下文敏感的,因此Git会将任何提交的提交合并到您当前正在工作的分支中。 pull  自动合并提交,而不让您先查看它们。如果您不密切管理您的分支机构,您可能会遇到频繁的冲突。

  • 当你 fetch,Git收集目标分支中当前分支中不存在的任何提交 将它们存储在本地存储库中。然而, 它不会将它们与您当前的分支合并。如果您需要使您的存储库保持最新,但是在更新文件时正在处理可能会中断的事情,这将非常有用。 要将提交集成到主分支中,请使用 merge


1850
2017-08-18 08:53



同意,好评。这就是为什么我讨厌git pull。什么时候让修改工具为您编写代码是否有意义?并不是合并两个文件正在做什么?如果这两个编辑在文件中是物理上分开的,但是LOGICALLY有点怎么办? - Lee Dixon
@elexhobby short put, git fetch 只更新你的 .git/ 目录(AKA:本地存储库),外面没什么 .git/ (又名:工作树)。它不会改变您的本地分支,也不会触及 master 无论是。它触动了 remotes/origin/master 虽然(见 git branch -avv)。如果您有更多遥控器,请尝试 git remote update。这是一个 git fetch 对于一个命令中的所有遥控器。 - Tino
@Tino你的确是最重要的一点。人们可能不知道“远程”分支实际上存储为一堆哈希 .git/refs/remotes/origin/。 - Chris
当你获取时,Git会收集目标分支中当前分支中不存在的任何提交,并将它们存储在本地存储库中  - 如何查看从遥控器带来的内容以及如何将其合并到我的本地分支机构? - アレックス
@Tino我还不明白的是......有什么意义?如果只更新,为什么要使用fetch .git?什么是预期的好处以及我之后应该做什么? - BadHorsie


将git的设计理念与更传统的源控制工具(如SVN)的理念进行对比非常重要。

Subversion是使用客户端/服务器模型设计和构建的。有一个存储库是服务器,几个客户端可以从服务器获取代码,对其进行处理,然后将其提交回服务器。假设客户端可以在需要执行操作时始终联系服务器。

Git旨在支持更加分散的模型而不需要中央存储库(尽管如果您愿意,您当然可以使用它)。此外,git的设计使客户端和“服务器”不需要同时在线。 Git的设计使得不可靠链接的人们甚至可以通过电子邮件交换代码。可以完全断开连接并刻录CD以通过git交换代码。

为了支持这个模型,git使用您的代码维护一个本地存储库,还有一个镜像远程存储库状态的附加本地存储库。通过在本地保留远程存储库的副本,即使无法访问远程存储库,git也可以找出所需的更改。稍后当您需要将更改发送给其他人时,git可以将它们作为一组更改从远程存储库已知的时间点进行传输。

  • git fetch是一个命令,说“使我的远程存储库的本地副本更新。”

  • git pull 说“将更改保存在我保留自己代码的远程存储库中。”

一般 git pull 通过做一个这样做 git fetch 使更改远程存储库的本地副本,然后将更改合并到您自己的代码存储库以及可能的工作副本中。

需要注意的是,至少经常会有这种情况 三份 您工作站上的项目。一个副本是您自己的存储库,具有您自己的提交历史记第二个副本是您正在编辑和构建的工作副本。第三个副本是远程存储库的本地“缓存”副本。


1008
2018-03-31 18:43



从技术上讲,本地和远程存储库实际上是同一个存储库。在Git中,存储库是一个 DAG 提交指向他们的父母。从技术上讲,分支只不过是有意义的提交名称。本地和远程分支之间的唯一区别是远程分支是前缀 remoteName/  Git从头开始 是一个非常好的阅读。一旦你了解了Git是如何工作的 - 它就是美妙的 简单,真的 - 一切都很有意义。 - Emil Lundberg
非常感谢您的解释。直到现在我才真正了解Git的设计,所以你不必拥有一个中央存储库。在描述Git时,每个人总是说“DVCS”,但作为一个相对较新的程序员,这对我来说毫无意义。我从来没有 看到 一个CVCS,我在与其他人(即Github)合作时也从未使用过中心远程存储库,所以直到现在我还没有理解是什么让Git变得特别。 - Brian Peterson
因此,基于此,为什么用cron作业进行git-fetch不是一个好主意?始终保留您在本地计算机上使用的遥控器的副本似乎是个好主意。事实上,我想编写一个脚本来检查我是否在过去24小时内更新了我的遥控器并将其与用于互联网连接的udev挂钩连接起来。 - Brian Peterson
有一个cron工作不是一个好主意的一个原因:通常在处理新票证或更新分支时,我喜欢看到正在获取的更改。如果在获取期间没有进行更改,我会更自信地问我的同事程序员'嘿,你推了吗?'。我也了解自上次提取以来存储库中的“流失”程度。这也有助于我了解当前对此存储库所做的更改的数量和速度。 - Michael Durrant
@Nabheet事情就是这样,Git是面向内容的。它只存储一次数据,并多次指向它。这就是为什么在Git中,即使是原始文件上的多个提交也不会对repo的大小产生太大影响,因为大多数对象都是相同的。 - cst1992


这是 奥利弗·斯蒂尔(Oliver Steele)将这一切融合在一起的形象

enter image description here

如果有足够的兴趣,我想我可以更新要添加的图像 git clone 和 git merge...


664
2018-06-09 13:30



更新后的图像 git clone 和 git merge 会非常有帮助的! - MEMark
是的,请添加 git merge  - 它应该清楚地表明 merge 单独调用与调用不同 pull 因为 pull 仅从远程合并并忽略您当地分支中的本地提交,该分支正在跟踪从中拉出的远程分支。 - JustAMartin
一张图片胜过千言万语!具有克隆和合并数据的更新映像是否已准备就绪?除了图中已有的数据流之外的任何其他数据流? - shikhanshu
@Contango请添加克隆和合并。对像我这样的新手有用。 - rents
有两个图表显示了由th3sly和thedarkpassenger在其他答案(下面)中克隆和合并。 - intotecho


一个用例 git fetch 以下将告诉您自上次拉动以来远程分支中的任何更改...因此您可以在执行实际拉动之前进行检查,这可能会更改当前分支和工作副本中的文件。

git fetch
git diff ...origin

428
2018-05-07 19:23



太棒了!我被点弄糊涂了,不是吗:git diff origin - harm
为什么不 git diff ..origin? - Erik Allik
git diff origin和git diff ..origin似乎工作但不是这个奇怪的东西 - Marc
@Compustretch不应该是一个空间。 git diff ...origin 相当于 git diff $(git-merge-base HEAD origin) origin (见 git diff [--options] <commit>...<commit> [--] [<path>…] 部分 kernel.org/pub/software/scm/git/docs/git-diff.html#_description),这是不同的 git diff origin; git diff ...origin 概念上是在做出的改变 origin 因为当前的分支从 origin,而 git diff origin 还包括当前分支自分支以来所做的更改的反向 origin。 - Max Nanasy
没有..命令对我有用(在Windows上),但是 git diff origin/master 工作,如下所述 - Brian Burns


我花了一点时间来理解有什么区别,但这是一个简单的解释。 master 在您的localhost中是一个分支。

克隆存储库时,将整个存储库提取到本地主机。这意味着那时你有一个原点/主指针 HEAD 和主人指向同一个 HEAD

当你开始工作并做提交时,你将主指针前进到 HEAD +你的提交。但是,原始/主指针仍指向克隆时的内容。

所以区别在于:

  • 如果你做了 git fetch 它只会获取远程存储库中的所有更改(GitHub上)并将原点/主指针移动到 HEAD。与此同时,您当地的分公司主人将继续指向它所在的位置。
  • 如果你做了 git pull,它将基本上进行提取(如前所述)并将任何新的更改合并到主分支并将指针移动到 HEAD

342
2018-05-11 18:37



origin / master是一个本地分支,它是一个原始版本的COPY。获取时,更新local:/ origin / master。一旦你确实认为git中的所有内容都是一个分支,这很有意义,并且是一种非常强大的方法来维护不同的变更集,快速本地分支,合并和变基,并且通常从廉价分支中获得很多价值模型。 - cam8001
仍然令人困惑。我想 git fetch 是按字面意思将远程仓库的更改下载到您的本地仓库,但不提交它们 - 即,它们仍然需要添加/提交到您的本地仓库。 - krb686
fetch仅从远程/原点(github)拉到本地原点。但它不会将其合并到您的实际工作文件中。如果您执行拉取,它将获取并合并到您当前的工作文件 - Gerardo


有时,视觉表示有帮助。

enter image description here


180
2018-01-25 17:28



我认为图片显示它也影响了当地的回购。也就是说,Git pull是影响本地回购和工作副本的组合。现在它似乎只影响工作副本。 - 太極者無極而生
@太极者无极而生同意 - 这个图像很容易误导,因为它看起来像 git pull 是 跳绳 获取,当然是不准确的。 - forresthopkinsa
@thedarkpassenger为什么不更新你的图像。然后,这将是新手的最佳拍摄。 ^^ - cmcromance
什么是“本地存储库”和“工作副本”之间的区别?他们都不是电脑本地人吗? - theITvideos


简要地

git fetch 类似于 pull 但不合并。即它获取远程更新(refs 和 objects)但你的当地人保持不变(即 origin/master 得到更新但是 master 保持不变)。

git pull 从遥控器上拉下来并立即合并。

更多

git clone 克隆回购。

git rebase 将当前分支中不在上游分支中的内容保存到临时区域。您的分支现在与开始更改之前的分支相同。所以, git pull -rebase 将下拉远程更改,回放本地分支,逐个重播您当前分支顶部的更改,直到您获得最新信息。

也, git branch -a 将向您展示您所有分支机构的确切情况 - 本地和远程。

这篇博文很有用:

git pull,git fetch和git clone(以及git rebase)之间的区别 - Mike Pearce

和封面 git pullgit fetchgit clone 和 git rebase

====

UPDATE

我想我会更新这个以显示你在实践中如何实际使用它。

  1. 从远程更新本地仓库(但不要合并):

    git fetch

  2. 下载更新后,让我们看看差异:

    git diff master origin / master

  3. 如果您对这些更新感到满意,请合并:

    git pull

笔记:

在第2步:有关本地和遥控器之间的差异的更多信息,请参阅: 将本地git分支与远程分支进行比较?

在第3步:做一个可能更准确(例如在快速变化的回购) git rebase origin 这里。请参阅另一个答案中的@Justin Ohms评论。

也可以看看: http://longair.net/blog/2009/04/16/git-fetch-and-merge/ 


166
2018-04-13 17:31



听起来好像有人只是想让本地代码反映“小费”,他们应该使用 git clone。我把小费放在引号中,因为我认为它意味着无论主人是什么以及有什么人会从github.com“下载为zip” - Chris K
如果你在git fetch之后对这些变化不满意怎么办?接下来做什么? - Kugutsumen
关于rebase的段落正是我所寻找的。关于将所有内容归零的整个想法,然后从远程更新 在之前的提交之前重播您的更改 那是你工作时发生的事。假设它是正确的完美解释。 ;) - coblr


git-pull  - 从另一个存储库或本地分支获取并合并
概要

git pull ...
描述

使用给定的参数运行git-fetch,并调用git-merge来合并
将头部检索到当前分支。使用--rebase,调用git-rebase
而不是git-merge。

请注意,您可以使用。 (当前目录)作为<repository>来拉
从本地存储库 - 这在合并本地分支时很有用
进入当前分支。

还要注意,选项意味着git-pull本身和底层的git-merge
必须在git-fetch的选项之前给出。

如果您想要合并历史记录,您可以选择,如果您只是想要“codez”,则可以获取,因为某些人已在此处标记了一些文章。


156
2017-11-15 09:52



非常有趣,但我真的看不到你想要“只是代码”的用例。以及获取时代码会发生什么?它被删除了吗?遥控器发生了什么变化?如果不合并,如何在没有删除代码的情况下进入您的仓库? - e-satis
@ e-satisf:远程分支也存储在您的机器本地。所以,当你这样做 git fetch 它从存储库中获取更改并更新本地远程分支。它不会影响跟踪本地远程分支的本地分支,因此不会影响您的工作副本。现在,当你做一个 merge 它会将获取的更改与您的本地分支合并。 - jeffreyveon
fetch命令的一个简单用例:执行涉及其他人最近提交的耗时操作,例如合并或代码审查,只访问最新的本地存储库而没有网络连接要求,因为您以前使用过fetch来下载您需要的所有内容(例如,当您访问其他开发人员并连接到其他存储库的网络时)。 pull命令会下载相同的提交,但它执行的合并可能是不合需要的。 - Lorenzo Gatti