【问题标题】:How to explain "git pull --rebase" in simple terms?如何简单地解释“git pull --rebase”?
【发布时间】:2018-05-16 08:08:54
【问题描述】:

我想我理解git pull,这就是我解释它的方式,我称之为“简单的术语”:

  1. 一般来说,git pull 是关于合并一个“远程”分支到一个“本地”分支。
  2. 更详细地说,git 使用“远程”分支的内容来“更新”/“修改”“本地”分支的内容。
  3. 更详细地说,如果一个文件在“local”分支中被修改,但在“remote”分支中没有被修改,那么在合并后,文件的内容将与“local”中的内容相同“ 分支。反之亦然。如果文件在“remote”分支上修改但不在“local”分支中,则内容将从“remote”分支获取。
  4. 如果文件在两个分支(“本地”和“远程”)中都被修改,那么 git 将尝试从两个分支中进行修改。如果更改发生在文件的不同位置,则这两项更改都将应用并在合并后出现在文件的内容中。
  5. 如果更改发生在同一个地方,我们就会遇到所谓的“合并冲突”,为简单起见,我不打算讨论这种情况。
  6. 由于合并,我们修改了“本地”存储库,因此我们需要“提交”。

现在我想为git pull --rebase 得到同样的解释。我不想使用诸如“head”、“index”、“fetch”、“upstream”之类的术语,因为这些术语/概念只会让像我这样的初学者感到困惑。我知道我需要学习这些“高级”概念,我通过阅读教程来做到这一点,但现在,作为我学习过程的一部分,我想了解git pull --rebase

添加

我想在某个时候我听到了以下解释。通过git pull --rebase。当我们合并时,我们不是以“对称”方式进行的,如上所述。相反,我们首先“忘记”“本地”存储库中的更改,只应用“远程”存储库中的更改。通过这样做,我们基本上“复制”了远程存储库。之后,我们应用顶部“本地”存储库中的更改。但是,我仍然不清楚这到底是什么意思。特别是“在上面”是什么意思。

【问题讨论】:

  • 请注意,git pull 是一个 git fetch 后跟一个 git merge。它实际上可能有助于理解什么是 HEAD 以及索引。如果你不这样做,如果事情没有按计划很快进行,你就会撞到沙洲。
  • 正如我在问题中所写,我不知道“获取”是什么意思。
  • @Roman,你现在做...
  • 不幸的是,正如亚历克西斯在他的回答中所说,“获取”不是一个高级概念。 Git 的索引也不是。 with fetch 和 with index 可以做的一些技巧是,但这两个是你必须理解的基本概念。正如@rubenvb 所指出的,如果您不知道索引的存在本身就会导致问题。这有点不幸,当我开始使用 Git 时也没有向我解释清楚。

标签: git git-rebase git-pull


【解决方案1】:

我看到有两件事可以澄清:您正在关注两个分支中文件的状态,但考虑正在发生的事情的更好方法是根据已发生的变更集。第二个问题是git pull 是两个操作的简写:git fetchgit merge。是的,你写道你“不想使用像fetch 这样的词”,但这不是一个“高级概念”。如果你想了解发生了什么,你需要从那里开始。

  • git fetch 本质上是通知本地仓库它不知道的更改。

  • git merge 将新到达的更改与您的本地更改统一起来。

问题是,如果两个 repos 上发生的事情没有同步,它们可能已经分道扬镳了:

... b--o--o--o--o  (remote)
     \
      x--x--x      (local)

上图从左到右显示时间;最右边的点是最近的。因此,新到达的更改是对文件旧状态的修改,即标记为“b”的文件。

  • git pull,即普通的git merge,将尽可能合并两个分支的最新状态。

  • git pull --rebase 会假装您的更改不是针对标记为“b”的状态,而是针对最新的远程状态。换句话说,它会尝试重写历史,使其看起来像这样:

    ... b--o--o--o--o              (remote)
                     \
                      x--x--x      (local)
    

这就是区别。一个后果是,如果你不 rebase,你的 repo 的历史记录包含一些状态(如果你愿意,你可以在将来回退到这些状态),其中应用了“x”更改但不存在“o”更改。 rebase 后,仓库中没有这个地方了。

【讨论】:

  • 感谢您非常明确的回答。我已经理解了您所写的所有内容,并且我了解了 fetchrebase 的含义。我唯一缺少的是知道我的本地分支的内容是否会根据我所做的git pullgit pull --rebase 而有所不同。换句话说,可以并行执行o-o-ox-x-x,然后合并给出与我们先执行o-o-o 然后执行x-x-x 时得到的内容不同的结果(内容)。换句话说,o-o-ox-x-x 是可交换操作吗?
  • @Roman:确实,在某些情况下,这些表现不佳,你会得到不同的结果。它们不是很常见,但确实存在。我建议 Git 新手完全避免使用 git pull:首先运行 git fetch,然后运行 ​​git merge 如果你想要合并,或者运行 git rebase 如果你想要 rebase。将两者分开可以让您有机会在两者之间运行git log,以便做出决定,并让您更清楚地了解正在发生的事情。
【解决方案2】:

简单:只要您的工作是本地的(意味着它没有被推送),git pull --rebase 将用于在更新的历史之上重播您的本地工作。

git fetch 将使用远程仓库的最新提交更新所述历史记录(例如origin/master)。
然后,您的工作(您的 master 分支的本地提交)将在更新的历史记录之上一一重播(这是变基所做的)。

这个想法是,当您想要推送时,所说的推送将非常简单,并且不需要合并,因为您的提交只是在 origin/master 之上完成的新提交。

请注意,您可以完全隐藏该变基部分since Git 2.6

git config pull.rebase true
git config rebase.autoStash true

即使变基不顺利并且您不得不中止,Git 也会为您恢复隐藏的当前工作since Git 2.10

【讨论】:

    猜你喜欢
    • 2018-08-02
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 2021-08-16
    • 2013-03-14
    • 2014-02-17
    相关资源
    最近更新 更多