我什么时候应该使用git pull --rebase?

Jas*_*ker 762 git

我知道有些人git pull --rebase默认使用,有些人坚持不使用它.我相信我理解合并和变基之间的区别,但我试图把它放在上下文中git pull.它只是不想看到很多合并提交消息,还是有其他问题?

sco*_*ode 707

我想提供一个关于"git pull --rebase"实际意味着什么的不同观点,因为它似乎有时会迷失.

如果您曾经使用过Subversion(或CVS),您可能会习惯"svn update"的行为.如果您有提交更改并且提交失败,因为已在上游进行了更改,则您将"svn update".Subversion通过将上游更改与您的上游进行合并来进行,可能会导致冲突.

Subversion刚刚做了什么,基本上是"拉动 - 基础".将本地更改重新制定为相对于较新版本的行为是其"重新定位"部分.如果你在失败的提交尝试之前完成了"svn diff",并且之后将得到的diff与"svn diff"的输出进行比较,那么两个差异之间的差异就是变基操作所做的.

在这种情况下,Git和Subversion之间的主要区别在于,在Subversion中,"您的"更改仅作为工作副本中的非提交更改存在,而在Git中,您在本地实际提交.换句话说,在Git中你已经分享了历史; 你的历史和上游历史有分歧,但你有一个共同的祖先.

在我看来,在正常情况下让你的本地分支只是反映上游分支并对其进行持续开发,正确的做法总是"--rebase",因为这是你在语义上实际做的事情.你和其他人正在破坏分支的预期线性历史.事实上,其他人在您尝试推动之前碰巧略微推动是无关紧要的,并且对于每次这样的事故导致合并的历史事件而言似乎适得其反.

如果你真的觉得无论出于什么原因需要某个分支,那么我认为这是一个不同的问题.但除非您有特定且积极的愿望以合并的形式表示您的更改,否则默认行为应该是"git pull --rebase".

请考虑需要观察和了解项目历史的其他人.您是否希望历史上散布着数以百计的合并,或者您是否只想要选择少数合并来代表有意的分歧开发工作的真正合并?

  • @MarceloCantos要清楚,我并不是说git(工具)应该默认为rebase.这将是危险的,因为篮板基本上破坏了历史.我说的是,就工作流程而言,当你不打算分支并且只是在其他人正在研究的某个分支上进行攻击时,"git pull --rebase"应该是用户的默认行为. (17认同)
  • 这个答案只是尝试使非分布式版本控制系统用户适应Git,而不是让他们有机会正确理解拥有适当分支的好处. (10认同)
  • @MarceloCantos不,我不是;)就个人而言,我会将autosetupmerge保留为t​​rue的默认值(如果我合并回到第四个除了本地< - >远程之外的分支之间,我喜欢它是明确的).我只是说作为一个人,我总是使用"git pull --rebase"作为我正常的"抓住最新的主分支"工作流程的一部分,因为除非我明确地分支,否则我永远不想创建合并提交. (9认同)
  • +1 @scode.在经历了许多痛苦的时间来解决这个问题,*最后*这里是一个指出它的答案. (7认同)
  • 惊人的!我在一家公司工作的策略是挑选不合并也不拉取请求,因此本地分支必须反映远程,我们应该总是在推送之前“更新”本地分支以避免代码审查工具中的冲突。我总是明确使用`git fetch &amp;&amp; git rebase`,它和`git pull --rebase`做同样的事情吗? (2认同)
  • @托马斯H。是的。Git-pull 的手册页显示:“在默认模式下,`git pull` 是 `git fetch` 的简写,后跟 `git merge FETCH_HEAD`。...使用 `--rebase`,它运行 `git rebase` 而不是`git 合并`。” (2认同)

P S*_*ved 546

你应该用git pull --rebase什么时候

  • 您的更改不值得单独的分支

确实 - 为什么不呢?它更清楚,并且不会对您的提交强加逻辑分组.


好吧,我想它需要一些澄清.在Git中,您可能知道,我们鼓励您进行分支和合并.您拉动更改的本地分支和远程分支实际上是不同的分支,并且git pull是关于它们的合并.这是合理的,因为你不经常推动并且通常在它们构成完整特征之前累积一些变化.

然而,有时 - 无论出于什么原因 - 你认为如果这两个 - 远程和本地 - 是一个分支实际上会更好.就像在SVN中一样.它在这里git pull --rebase发挥作用.您不再合并 - 您实际上在远程分支上提交.这就是它的实际意义.

无论是否危险,问题在于你是否将本地和远程分支视为一个不可分割的东西.有时它是合理的(当你的变化很小时,或者如果你处于强劲发展的开始阶段,当小的提交带来重要的变化时).有时它不是(当你通常创建另一个分支,但你懒得这样做).但这是一个不同的问题.

  • 我认为当你在同一个分支上工作时它很有用,但你可以改变你的工作站.我倾向于从一个工作站提交并推送我的更改,然后在另一个工作站中提取rebase,并继续在同一个分支上工作. (15认同)
  • 使用`git config --global pull.rebase preserve`将Git设置为自动重新绑定是一个有用的最佳实践(保留说除了启用变基,如果你在本地制作任何变量,试图保留合并). (11认同)
  • 我不同意仅在一个分支上工作时才应使用pull --rebase。您应该一直使用它,除非由于其他情况而无法使用。 (2认同)
  • 我认为值得注意的是,冲突无论如何都会导致合并。 (2认同)

Cod*_*oll 184

也许最好的解释方法是举个例子:

  1. Alice创建主题分支A,并对其进行处理
  2. Bob创建了不相关的主题分支B,并对其进行处理
  3. 爱丽丝git checkout master && git pull.师父已经是最新的.
  4. 鲍勃git checkout master && git pull.师父已经是最新的.
  5. 爱丽丝 git merge topic-branch-A
  6. 鲍勃 git merge topic-branch-B
  7. 鲍勃git push origin master在爱丽丝面前做
  8. 爱丽丝做了git push origin master,因为它不是快进合并而被拒绝.
  9. Alice查看origin/master的日志,发现提交与她的无关.
  10. 爱丽丝 git pull --rebase origin master
  11. Alice的合并提交被解除,Bob的提交被撤销,并且在Bob的提交之后应用Alice的提交.
  12. Alice确实如此git push origin master,并且每个人都很高兴他们在将来查看日志时不必阅读无用的合并提交.

请注意,要合并的特定分支与示例无关.在这个例子中,Master可以很容易地成为发布分支或dev分支.关键点在于Alice和Bob同时将其本地分支合并到共享远程分支.

  • “Alice 的提交在 Bob 的提交之后应用”也许值得注意的是,在这种情况下,Alice 的提交的提交哈希确实发生了变化。 (3认同)
  • 真好 我倾向于露骨,`git co master &amp;&amp; git pull; git checkout topic-branch-A; git rebase master; git checkout master; git merge topic-branch-A; git push origin master`,如果另一个在我之前进行过,则重复此操作。虽然我可以在您的食谱中看到简洁的优势。 (2认同)
  • 我不明白。如果两个人修改的内容不相关,则修改的内容之间不应该有冲突。为什么在这种情况下不允许推送? (2认同)
  • @alalalala 当这些分支被创建时,它们是基于 master 的 HEAD 的。当branch-B合并时,master的HEAD发生了变化。如果 B 的分支有 5 次提交,则分支 A 所知道的前一个 HEAD 在 B 合并后将变为 HEAD-5。所以现在,分支 A 不知道它去了哪里。它只确定它会在 HEAD-5 之后进行,但现在还有 5 个其他提交!它是在 HEAD 之后还是在 HEAD 之前和 HEAD-5 之后的某个地方?做 rebase 回答了这个问题,说:“你去 *after* HEAD。” 它不再“基于”(旧的)HEAD-5。它现在“基于”(新的)HEAD。因此:变基(d)! (2认同)

kro*_*old 143

我认为你应该git pull --rebase在与同一分支上的其他人合作时使用.你正在工作→提交→工作→提交周期,当你决定推动你的工作时,你的推动被拒绝,因为在同一个分支上有并行工作.在这一点上,我总是做一个pull --rebase.我不使用squash(以展平提交),但我重新设置以避免额外的合并提交.

随着您的Git知识的增加,您发现自己在历史上看起来比我使用的任何其他版本控制系统更多.如果你有大量的小合并提交,很容易失去你历史上正在发生的大局的焦点.

这实际上是我唯一一次进行变基(*),而我的工作流程的其余部分都是基于合并的.但只要你最常见的提交者这样做,历史最终会看起来好多了.

(*)在教授Git课程的同时,我让一名学生逮捕了我,因为在某些情况下我也主张改变特色分支.并且他已经阅读了这个答案;)这种变基也是可能的,但它总是必须根据预先安排/商定的系统,因此不应该"始终"应用.那时我通常都不做pull --rebase,这就是问题所在;)

  • 实际上,它已经存在:`git log --no-merges` (35认同)
  • @hasen j是的,但这些合并的内容可能很重要 (9认同)
  • 合并也可以包含差异,这意味着它并非完全无关紧要 (3认同)
  • 当然可以编写一个脚本来隐藏日志中的合并提交 (2认同)
  • 围绕“branch”的模糊性是有意为之的,因为使用 ref 的方法有很多;“工作线”只是一种选择。 (2认同)

Dus*_*tin 48

我不认为有任何理由使用pull --rebase- 我特意为Git添加了代码以允许我的git pull命令总是反对上游提交.

查看历史记录时,知道何时处理该功能的人/ gal停止同步是非常有趣的.当他/她这样做时,它对于那个人/ gal可能是有用的,但这reflog就是为了什么.这只会为其他人增加噪音.

  • 是的,他们也不是"整个国家".这就是我们不想要它们的原因.我想知道他想要什么,而不是他如何到达那里. (10认同)
  • 如果你从"上游"拉出来,那么这似乎是一个很好的建议,比如来自`master`,如果你进入的分支还没有公开(还).如果你把另一只手从一个功能分支拉到`master`,那就更像是另一种方式:从来没有理由使用`--rebase`,对吗?这可能是它不是默认的原因._I发现Rebases是更改应该从层次结构顶部向下传递的方式,合并是它们向上流回的方式._ https://www.derekgourlay.com/blog/git-when-to-merge-vs-when-to-变基/ (8认同)
  • 如果应该总是使用`pull --rebase`,那么为什么默认不执行`pull`呢? (4认同)
  • "在查看历史记录时,知道处理该功能的人何时停止同步是绝对有趣的." /但这是否意味着那些中间提交可能是破坏的构建? (2认同)
  • 我担心你不得不形成自己的意见.我的`.gitconfig`中有几个东西让一些选项做正确的事.我认为git rebase默认做错了,git tag等也是如此......如果你不同意,你不需要证明自己的观点是正确的. (2认同)

小智 31

只记得:

  • pull = fetch + merge
  • pull --rebase = fetch + rebase

因此,选择您想要处理分支的方式.

你最好知道merge和rebase之间的区别:)

  • 这并没有解决何时使用 rebase 的问题。 (13认同)

小智 11

此场景描述了由于源代码已更改而无法推送提交的情况。科迪的解释很容易理解。我画了一张图来描述这个场景,希望对你有所帮助。如果我错了,请纠正我。

在此输入图像描述


has*_*sen 9

我认为这归结为个人偏好.

你想在推动改变之前隐藏你的愚蠢错误吗?如果是这样,那就git pull --rebase完美了.它允许您稍后将提交压缩到几个(或一个)提交.如果您在(未按下的)历史记录中进行了合并,那么稍后进行合并就不那么容易了git rebase.

我个人不介意发布我所有的愚蠢错误,所以我倾向于合并而不是rebase.

  • 观看此问题的任何人都要注意:这个答案与"我应该何时使用git pull --rebase?"这个问题完全无关. (6认同)
  • @therealklanni我编辑了答案,以便更清楚地了解它与问题的相关性(希望不会破坏意图). (3认同)
  • 共享肮脏且无组织的工作日志并不是一种诚实的努力,而只是懒惰。你让人们在你的开发和调试兔子洞中追着你,这是在浪费他们的时间;给他们结果,而不是胡言乱语。 (2认同)

Hab*_*bax 7

git pull --rebase可能隐藏合作者的历史改写git push --force。我建议git pull --rebase 在您知道在其他人之前忘记推送您的提交之前使用。

如果您什么也没做,但是您的工作空间不干净,就git stash在之前git pull。这样,您将不会默默地重写您的历史记录(这可能会默默地删除您的某些工作)。

  • @user18099 假设您(A)和其他人(B)正在同一个分支上工作。B 推送他们的提交 1,你推送你的提交 2,B 在不拉动你的工作的情况下修改他们的提交 1,然后强制推送。如果您拉动变基,您将丢失提交 2 及其包含的所有工作。 (5认同)
  • 在您描述的场景中,您不会“默默地丢失提交 2”。在变基步骤期间,提交 2 和修改后的提交 1 之间的差异仍然在本地应用。你不会失去你的工作。 (3认同)
  • 这是一个很好的经验法则——拉动之前先藏起来 (2认同)

Dee*_*rma 6

一个实践案例是您使用 Bitbucket PR 时。我们通过下面的案例来理解一下:

有公关开放。

然后,您决定通过 BitBucket GUI 使用最新的 Master 分支对 PR 远程分支进行变基。此操作将更改您的 PR 的提交 ID。

因为您已经使用 GUI 重新建立了远程分支的基础。首先,您必须将 PC 上的本地分支与远程分支同步。

在这种情况下git pull --rebase就像魔术一样。

git pull --rebase您的本地分支和远程分支具有相同的历史记录和相同的提交 ID 后。

现在,如果您向 PR 分支添加新的提交/更改。

您可以很好地将新提交推送到远程分支/BitBucket PR,而无需使用强制或任何其他方式。