在Git中,fetch和pull有什么区别?merge和rebase又有什么不同?

169

我实在是不理解这个问题。我已经在网上和书本上读了很多,但仍然有些东西没有留在我的脑海中。可以有人给我以下操作的简单版本吗?:

  • git fetch 与 pull 的区别
  • git merge 与 rebase 的区别

24
我理解问者的感受。文档和建议内容非常繁重,可能的工作流程组合也非常庞大,以至于人们会感到极度困惑。人们的头脑会变得混乱,不知道该问什么,问题并不那么明显。 - Ed Randall
3
为什么不选择Pestrella的答案作为采纳答案? - Arashsoft
@Arashsoft因为自2013年以来没有出现。 - VedantK
4个回答

439

fetch vs pull

fetch将下载远程*分支的任何更改,更新您的存储库数据,但不会更改您的本地*分支。

pull将执行fetch并将更改合并到您的本地分支中。

有什么区别?pull使用来自提取的分支的更改更新本地分支。 fetch不会推进您的本地分支。

merge vs rebase

给定以下历史记录:

          C---D---E 本地
         /
    A---B---F---G 远程

merge将两个开发历史记录连接在一起。 它通过在远程分支之上重放发生在本地分支分叉后的更改,并在新提交中记录结果来完成此操作。 此操作保留每个提交的祖先关系。

一个merge的效果将是:

          C---D---E 本地
         /         \
    A---B---F---G---H 远程

rebase将接受存在于您的本地分支中的提交,并将它们重新应用在远程分支之上。 此操作将重写您本地提交的祖先关系。

一个rebase的效果将是:

                  C'--D'--E' local
                 /
    A---B---F---G remote

有什么区别?merge不会更改提交的祖先关系。 rebase重写了您本地提交的祖先关系。

* 此解释假设当前分支是本地分支,并且作为fetchpullmergerebase参数指定的分支是远程分支。这是通常的情况。pull,例如,将下载任何来自指定分支的更改,更新存储库并将更改合并到当前分支中。


33
非常简洁易懂的解释,而且没有涉及到每个实践背后的争议。谢谢! - Jonathan S. Fisher
3
绝对金牌回答。 - ChaseMoskal
5
希望我能够“收藏”这个答案。也许我只需将其打印并粘贴在墙上。 - LarsH
2
我会说这是我在stackoverflow上得到的最好的答案,谢谢。 - Shahab J
1
这是更详细的解释,类似于这里:https://www.derekgourlay.com/blog/git-when-to-merge-vs-when-to-rebase/ - tozka
显示剩余3条评论

29

抓取(Fetch)与拉取(Pull)

Git 抓取只是更新您的仓库数据,但 git 拉取将执行抓取然后合并拉取的分支。

git pull 和 git fetch 有什么区别?


合并(Merge)与变基(Rebase)

来自 Atlassian SourceTree Blog 的 Merge or Rebase

合并将两个开发分支合并在一起,同时保留每个提交历史记录的祖先关系。

相比之下,变基通过重新编写源分支的更改,使它们出现在目标分支的子级位置,从而统一了开发分支 - 事实上,它假装这些提交一直都是在目标分支上编写的。

还可以查看Learn Git Branching,这是一个很好的游戏,刚刚发布到 HackerNews (帖子链接),可以教授很多分支和合并技巧。 我相信这对这个问题非常有帮助。


谢谢Felips。所以,如果我从远程获取(fetch)数据,我的主分支(master branch)将不会有更新?同时听起来我应该更多地使用rebase而不是merge。 - techsjs2013
rebase和merge的选择取决于你的意图,要记住rebase会重写所有提交历史记录。如果你只是fetch,那么主分支不会被改变,你需要合并(或拉取)才能应用远程更改。 - Felipe Sabino
git merge <remote>/<branch>。例如,如果您在主分支上,并且您的远程名称为origin,则可以执行git merge origin/master - Felipe Sabino
看起来我应该总是执行以下操作: git checkout master git fetch git diff origin/master git rebase origin master - techsjs2013

11

pull vs fetch:

据我理解,git pull 简单来说就是 git fetch 加上 git merge。也就是说,你从远程分支获取变更,然后将其合并到当前分支。


merge vs rebase:

使用合并命令会将当前分支与指定分支之间的差异进行合并(到当前分支)。比如说,git merge another_branch 命令会将 another_branch 合并到当前分支。

而使用变基命令则有所不同,它非常强大。假设你执行了命令 git rebase another_branch,Git 首先会找到当前分支和 another_branch 的最新公共版本,即这两条分支在分叉前的那个点。然后 Git 会将这个分叉点移动到 another_branch 的最新提交处。最后,所有自分叉点以来当前分支中的提交都被“重演”到新的分叉点上。这样就创建了一个非常干净的历史记录,减少了分支和合并操作。

但是,这样做也有风险!因为版本历史被“重写”了,所以只有当提交只存在于你的本地 Git 仓库中时,才应该这样做。也就是说:如果你已经将提交推送到远程仓库,那么千万不要操作。

这本在线书籍中,有一份非常好的关于变基的解释和易于理解的插图。


pull with rebasing instead of merge

实际上,我经常使用变基命令,但通常与 pull 命令结合使用:

git pull --rebase

将获取远程更改,然后重新定位到基底位置而不是合并。即,它将重放所有你自上次执行拉取以来的本地提交。我认为这比使用常规合并进行普通拉取更加清晰,因为它会创建一个带有合并的额外提交。


如果我正在一个分支上工作,并且想在推送之前将其合并回主分支。我应该检出主分支,然后执行get rebase fix吗? - techsjs2013
我仍然不理解合并(merge)和变基(rebase)的区别。 - techsjs2013
我认为pestrella的回答提供的插图非常清晰地展示了差异。另外,可以查看:http://git-scm.com/book/en/Git-Branching-Rebasing - 这本书做了相当不错的解释(与答案中的链接相同,但再次给出以方便懒惰的人)。 - Steinar

0

合并 - HEAD分支将生成一个新的提交,保留每个提交历史的祖先。如果多个人在同一分支上并行工作,则历史记录可能会变得污染。

变基 - 将一个分支的更改重写到另一个分支上,而不创建新的提交。代码历史简化、线性和可读,但它不能与拉取请求一起使用,因为你看不到其他人所做的微小更改。

当处理基于特性的工作流程或者我不熟悉变基时,我会使用git merge。但是,如果我想要一个更干净、线性的历史记录,那么git rebase更加适合。有关更多详细信息,请务必查看this merge or rebase article


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接