重新定位以及通过rebasing推动提交意味着什么

Hem*_*mar 105 git rebase

人们常说,你不应该重新提出你已经推过的提交.这可能意味着什么?

pse*_*der 235

要理解这一点,我们需要了解一下git是如何工作的.git存储库是树结构,其中树的节点是提交.这是一个非常简单的存储库的示例: 当你分叉

它在master分支上有四个提交,每个提交都有一个ID(在这种情况下,a,b,c和d).您会注意到d当前是主分支的最新提交(或HEAD). 在此输入图像描述

在这里,我们有两个分支:master和my-branch.您可以看到master和my-branch都包含提交a和b,但随后它们开始发散:master包含c和d,而my-branch包含e和f.与主人相比,b被称为my-branch的"合并基础" - 或者更常见的是,只是"基础".这是有道理的:您可以看到my-branch基于以前版本的master.

所以,让我们说my-branch已经过时了,你想让它与最新版本的master保持同步.换句话说,my-branch需要包含c和d.您可以进行合并,但这会导致分支包含奇怪的合并提交,这使得审查拉取请求变得更加困难.相反,你可以做一个rebase.

在此输入图像描述

当你重新绑定时,git找到你的分支的基础(在这种情况下,b),找到该基和HEAD之间的所有提交(在这种情况下,e和f),并在分支的HEAD上重新播放这些提交你正在改变(在这种情况下,主人).Git实际上创建了新的提交,表示你的更改在master之上的样子:在图中,这些提交称为e'和f'.Git不会删除你以前的提交:e和f保持不变,如果rebase出现问题,你可以回到以前的状态.

当许多不同的人正在模拟地处理项目时,拉取请求可能会很快变得陈旧."陈旧"拉取请求是与主要开发线不再同步的请求,并且需要在合并到项目之前进行更新.拉请求过时的最常见原因是由于冲突:如果两个pull请求都修改了同一文件中的相似行,并且一个pull请求被合并,则unmerged pull请求现在将发生冲突.有时,拉请求可能会在没有冲突的情况下变得过时:代码库中不同文件的更改可能需要对您的pull请求进行相应更改以符合新架构,或者当有人意外地将失败的单元测试合并到主分公司.无论原因如何,


Tim*_*gan 79

ProGit本书有一个很好的解释.

您可以在标题为"重新定位的危险 "一节中找到您问题的具体答案.该部分的引用:

当您重新设置内容时,您将放弃现有提交并创建相似但不同的新提交.如果你将提交推送到某个地方而其他人将它们拉下来并依赖它们,然后你用git rebase重写这些提交并再次推送它们,那么你的协作者将不得不重新合并他们的工作,当你试图将事情变得混乱把他们的工作拉回你的工作.

更新:
根据您在下面的评论,听起来您的Git工作流程有困难.以下是一些可能有用的参考资料:


Jör*_*tag 68

重新定位重写历史记录.如果没有人知道那段历史,那就完全没问题了.然而,如果历史是公开的,那么在Git中重写历史就像它在现实世界中所做的那样:你需要一个阴谋.

阴谋真的很难保持在一起,所以你最好避免首先重新定位公共分支机构.

请注意,成功的阴谋的例子:puJUNIO C.滨野的git仓库的分支(Git的SCM的官方资料库)经常重订.这种方式的工作方式是,几乎每个使用的人都pu订阅了Git开发人员的邮件列表,并且该pu分支被重新定位的事实在邮件列表和Git网站上被广泛宣传.

  • "在Git中重写历史就像它在现实世界中所做的一样:+1,你需要一个阴谋" (25认同)
  • +1.我认为git.git的`pu`分支是一个非常有用的例子,说明如何在(公共)工作流中使用rebase.对于那些不熟悉它的人来说,一般的想法是重新定义在`next`中没有任何提交的主题分支(在合并到master之前的不稳定分支),然后通过重置为`next`来重建`pu`分支. ,并合并所有主题分支.(来源:Documentation/howto/maintain-git.txt http://git.kernel.org/?p=git​​/git.git;a=blob;f=Documentation/howto/maintain-git.txt;h=d527b307707c676e82a08f18cb9fdd7d3abcb228 ; hb = HEAD) (4认同)

dso*_*ano 6

rebase会改变存储库的历史记录.如果您将提交推送到世界,即将其提供给其他人,然后您更改了对提交历史的视图,则很难与具有旧历史的任何人一起工作.

我认为Rebase被认为是有害的,是一个很好的概述.