【问题标题】:Difference between git pull, git fetch+merge and git rebasegit pull、git fetch+merge 和 git rebase 的区别
【发布时间】:2018-03-05 16:36:40
【问题描述】:

我在git pullgit fetch + git mergegit rebase 之间感到困惑。 它们似乎都执行相同的功能,那么它们之间的区别特别是在提交日志方面。

如果远程分支和本地分支都有变化,那么在所有三种情况下,谁的提交将首先出现。

【问题讨论】:

标签: git git-merge git-rebase git-pull


【解决方案1】:

正如您在问题中所暗示的那样,其中最令人困惑的部分是了解与远程存储库相比对本地存储库的影响,以及对使用远程存储库的其他所有人的影响。

首先,正如其他答案所示,git pullgit fetch + git merge 字面上相同。这两个命令都是从本地仓库拉取/获取 + 合并从远程到本地仓库的角度来看的。这发生在您在远程本地签出到本地该分支的同一个分支上。我会先讨论这些,然后再讨论压缩和变基。

Git 拉取 / Git Fetch + Git 合并

假设您已在本地签出master,然后您将从远程获取master(除非您在这些命令上使用一些更高级的语法或标记)。我们将远程分支称为origin/master

origin/master 获取意味着您希望从origin/master 获取新提交并更新origin/master 的本地跟踪参考以匹配master 实际在远程的位置。如果master 在本地和远程之间存在分歧,那么将会有提交从您的主分支分支出来,直到它们到达origin/master 引用的当前位置。您最近未推送的提交将位于可能不同的本地 master 分支上。

然后,当合并发生时,您基本上要求将 origin/master 合并到您本地的 master 分支中。如果您执行正常的合并命令,这将导致对本地 master 分支的新提交将所有最近的更改从 origin/master 拉入本地 master 分支。如果有冲突,您将在提交之前先解决它们。但是,如果您没有在本地提交任何内容,则合并可以快速前进到新的 origin/master 位置,而无需执行任何其他操作(您的 master 将向前跳转以匹配 origin/master)。

此时,如果您在其他任何人向远程推送更多内容之前推送,那么您的新合并提交将与您的单独提交(它们看起来像一个单独的、未命名的分支)和原始远程提交一起推送,最后加上一个新的合并提交。

挤压呢?

您确实问过这个问题,但是如果您与 --squash 合并,那么它将添加合并提交,但删除其他本地提交,因此历史记录中没有额外的未命名分支。有些人更喜欢它,因为它“更干净”,而另一些人则更喜欢查看所有历史记录(即代码分歧以及合并提交中究竟汇集了什么)。

变基

当您变基时,您基本上是在获取所有本地提交,并将它们重播到远程主分支上,因此它们不会显示为单独的分支。这使本地历史保持完整,而没有显示代码分歧,同样,有些人更喜欢并认为它更“干净”。这与任何历史记录是否重要等无关。

如果其他人在我获取后提交了怎么办?

如果其他忍者在您获取后提交(嗯,只是提交......),那么您的推送将失败。你可以使用--force,但是你会完全覆盖他们的提交,所以这通常是不受欢迎的,因为它会给其他人带来各种各样的问题。在这种情况下,如果每个人都同意他的提交应该先进行,那么您将需要再次执行该过程(如果没有冲突,那么这将是快速而简单的),但总的来说,团队需要有一个策略在这类事情上,一旦团队足够大,通常会使用拉取请求和审查来以更有序的方式管理推送。

另一种思考方式

将本地主分支视为与远程分支分开的分支,可能很容易理解正在发生的事情 - 从 Git 的角度来看,这基本上是正在发生的事情。

事实上,在我看来,在你准备好将某些东西合并到远程分支之前,你总是最好在自己的单独分支中工作。 Git 让拥有一个单独的分支变得如此简单、快速和轻松,这就是我所做的。

【讨论】:

    【解决方案2】:

    使用一些谷歌。 git pull=git fetch 后跟 git merge。谷歌搜索时第一次点击git pull:https://git-scm.com/docs/git-pull:

    在其默认模式下,git pull 是 git fetch 后跟 git merge FETCH_HEAD 的简写。

    git rebase 完全不同,与遥控器无关。再次,谷歌可以解决你的问题,但是一个简短的图形解释,当站在分支 A 上,并在 B 之上重新定位(这与站在 A 上不同,合并 B 进入 它):

    c1-c2-c3<-A
     \-c4-c5<-B
    

    变成

    c1-c4-c5-c2-c3<-A
           ^
           B
    

    我们在这里所做的是将 A 上的不同提交(我们正在进行)并将它们应用到 B 之上,基本上删除了分支结构。永远不会有像“合并提交”这样的“变基提交”。这与远程无关,除了git pull --rebase 将获取然后将您的本地更改重新设置在远程更改之上,而不是将远程更改合并到您的本地提交中。同样,google.com 或 git-scm.com/docs。

    【讨论】:

      【解决方案3】:

      来自 git 文档

      git pull 将远程存储库中的更改合并到当前分支中。在其默认模式下,git pullgit fetch 后跟 git merge FETCH_HEAD 的简写

      rebase 在另一个基本提示之上重新应用提交。

      所以你可以在fetched 之后做git rebase FETCH_HEAD

      如果你有

      (*) <-- HEAD
       |
      (*) <-- commit B
       \   (*) <-- origin/master
        \  /
         (*) <-- commit A
      

      如果你使用rebase,git 会回退你的 HEAD 以提交 A 并应用按日期排序的所有提交

      如果您使用merge,git 会将两个分支合并为一个分支,将您的提交应用到origin/head 的顶部

      【讨论】:

        猜你喜欢
        • 2011-03-22
        • 2011-09-11
        • 2020-08-24
        • 2017-06-30
        • 2014-10-15
        • 2018-04-28
        • 2014-03-12
        • 2013-05-15
        相关资源
        最近更新 更多