远程git rebase如此邪恶的详细原因

远程git rebase如此邪恶的详细原因,git,git-rebase,Git,Git Rebase,因此,我来自一个集中的VCS背景,并试图用Git(新公司,young code base)确定我们的工作流程。有一个问题我找不到一个简单但详细的答案,那就是远程分支上的rebase到底做了什么。据我所知,它改写了历史,一般只限于当地分支机构 我目前尝试检查的工作流涉及一个远程协作分支,每个开发人员“拥有”一个分支,用于共享代码。(在可预见的未来,每个项目和功能请求有2个开发人员和最多3个功能分支,这似乎是过度的,而且开销大于收益。) 然后我偶然发现并尝试了它,它实现了我想要的——开发人员经常提交

因此,我来自一个集中的VCS背景,并试图用Git(新公司,young code base)确定我们的工作流程。有一个问题我找不到一个简单但详细的答案,那就是远程分支上的rebase到底做了什么。据我所知,它改写了历史,一般只限于当地分支机构

我目前尝试检查的工作流涉及一个远程协作分支,每个开发人员“拥有”一个分支,用于共享代码。(在可预见的未来,每个项目和功能请求有2个开发人员和最多3个功能分支,这似乎是过度的,而且开销大于收益。)

然后我偶然发现并尝试了它,它实现了我想要的——开发人员经常提交并推送到自己的协作分支,当他知道批准发布到staging的内容时,他可以在合并到develope之前远程重新设置基础(挤压,也许重新组织)


输入原始问题-如果远程分支是为了协作,那么其他人迟早会拉它。如果“客户开发人员”没有向该协作分支机构承诺这是一个流程/培训问题,那么分支机构所有者会对该远程分支机构进行重新定基吗?

对已发布(远程)分支机构进行重新定基(或重写历史)的主要问题是,很难根据这些分支机构重新整合工作。因此,如果这些远程设备只是为了查看而获取的,并且在这些远程设备之上没有提交,甚至没有进行合并,那么通常不会有太多问题。否则,合并和解决冲突可能很快成为主要的麻烦

这并不是真的邪恶,而是实现和期望的问题

我们从错综复杂的事实开始:

  • 每个Git散列都代表一些唯一的对象。在这里,我们只需要考虑提交对象。每个散列都是对对象内容应用加密散列函数(对于Git,特别是SHA-1)的结果。对于提交,内容包括源树的ID;作者和提交人的姓名、电子邮件地址和时间/日期戳;提交消息;这里最关键的是,父提交的ID

  • 即使只更改内容中的一个位,也会产生一个新的、非常不同的哈希ID。哈希函数的加密属性,用于对每个提交(或其他对象)进行身份验证和验证,这也意味着没有办法让某些不同的对象具有相同的哈希ID。Git也依赖于此在存储库之间传输对象

  • 通过将提交复制到新的提交,重基(必然)起作用。即使没有其他更改,而且通常与新副本关联的源代码与原始源代码不同,重基的整个要点是重新设置某个提交链的父级。例如,我们可以从以下内容开始:

    ...--o--*--o--o--o   <-- develop
             \
              o--o       <-- feature
    
    其中两个
    @
    是原始两个提交的副本

  • 分支名称,如
    develope
    ,只是指向(单个)提交的指针。我们通常认为是“一个分支”的东西,比如两个提交--,是通过从每个提交向后工作到其父级而形成的

  • 分支总是希望增加新的提交。发现
    develope
    master
    添加了一些新的提交是完全正常的,因此名称现在指向一个提交,或者指向名称所指向位置的许多提交中的最后一个

  • 每当您让Git将您的存储库与其他Git及其存储库进行同步(无论达到何种程度),您的Git和他们的Git都会交换ID,特别是哈希ID。具体哪个ID取决于传输的方向,以及您要求Git使用的任何分支名称

  • 远程跟踪分支实际上是Git存储的与存储库关联的实体。你的远程跟踪分支
    origin/master
    实际上是你的Git用来记住“我们上次谈话时,
    origin
    的Git说他的
    master
    是什么。”

现在,我们来看这七个项目,看看
git fetch
是如何工作的。例如,您可以运行
git fetch origin
。此时,Git在
origin
上调用Git并询问它的分支。他们说的是
master=1234567
branch=89abcde
(尽管散列值的长度都正好是40个字符,而不是这些7个字符)

您的Git可能已经有了这些提交对象。如果是这样,我们就快完成了!如果没有,它会要求他们的Git发送这些提交对象,以及Git需要的任何其他对象来理解它们。附加对象是与这些提交一起使用的任何文件,以及这些提交使用的您尚未拥有的任何父提交,加上父提交的父提交,依此类推,直到我们得到您确实拥有的某些提交对象。这将获得所有新历史记录所需的提交和文件。1

一旦Git安全地存储了所有对象,Git就会用新ID更新远程跟踪分支。他们的Git刚刚告诉您,他们的
主控
1234567
,所以现在您的
源/主控
设置为
1234567
。它们的
分支也是如此:它成为您的
源/分支
,您的Git保存
89abcde
散列

如果您现在
git checkout branch
,您的git将使用
origin/branch
创建一个新的本地标签,指向
89abcde
。让我们画这个:

...--o--*--o--1   <-- master, origin/master
         \
          o--8    <-- branch, origin/branch
(我把
aaaaaaa…
缩短为
A

那么,一个有趣的问题是,如果他们从Git中获取重基信息,会发生什么。比如说,假设他们是reba
...--o--*--o--1   <-- master, origin/master
         \
          o--8    <-- branch, origin/branch
...--o--*--o--1    <-- master, origin/master
         \
          o--8     <-- origin/branch
              \
               A   <-- branch
...--o--*--o--1        <-- master, origin/master
         \     \
          \     o--F   <-- origin/branch
           \
            o--8--A    <-- branch