GIT rebase 需要重新提交更改

2023-12-05

首先,我是 git 分支的新手。我不知道每个功能分支都应该从master并且仅使用与下一个功能分支具有这种关系的先决功能分支。

我有三个分行。master, feature-1 and feature-2全部推送到 Bitbucket 存储库(启用问题跟踪)。事情是承诺M4 and M5是关键提交,所有分支都应该在提交合并之前对其进行变基(任务git rebase)

M1 -- M2 -- M3 -- M4 -- M5   [master]
  \        /
   A1 --- A2                 [feature-1]
           \
            B1 -- B2 -- B3   [feature-2]

发展为feature-2已完成,现在需要合并到 master 中。这是我已完成的任务的优先级feature-2重新设定基准M4 and M5承诺feature-2.

  1. git push- 发展feature-2
  2. git checkout feature-2
  3. git rebase master
  4. 解决冲突
  5. git pull

完成这些步骤后我注意到执行后git status。我必须再次推送所有提交(feature-2, M4, M5和冲突提交)。好吧,我所要做的就是做git push并发起拉取请求,我就完成了,对吗?但这会向问题跟踪器添加另一个 git commit 注释。

有没有办法重新建立基础feature-2 to master无需再次推送提交feature-2, M4 and M5git log应该包含冲突提交。

Update

  • 更改问题详细信息以获得更好的说明

由于您已经推送了两个功能分支,因此您根本不应该进行变基。强烈建议不要对已发布的分支进行变基,因为它会破坏其他开发人员的存储库。原因是 rebase 只是一个完全重写的提交。您正在变基的提交将被重新创建,内容已更改,并且最重要的是具有不同的哈希值。这会导致新提交与旧提交不兼容,因此无论谁拥有旧提交,最终都会与取代它们的新提交发生冲突。

正确的解决方案是简单地合并更改。虽然这可能最终看起来不太漂亮,但这是一种非破坏性操作,不会更改现有的提交。所发生的只是提交是added这不会导致推或拉时出现问题。

话虽这么说,你can变基并仍然发布更改的分支。但要做到这一点,您将需要强制推送分支,而拉动这些更改的其他开发人员将需要将其分支重置为新版本。


将我下面的一些评论合并到答案中:重要的是要理解,在 Git 中,分支只是指向提交的指针。整个历史(没有分支)是一个大型非循环图,其中提交仅指向其父提交。因此,以问题中的示例为例,这是历史记录,没有任何分支指针:

A -- B -- C -- D -- E
 \       /
  F --- G
         \
          H -- I -- J

每个字母代表一个提交,并且所有提交都连接到向左转是它的父级。例如F的父级是A, and C是与父母的合并提交B and G.

现在,如果我们向该可视化添加分支,那么我们只需添加指向某些提交的指针。它实际上没有别的(分支实际上只是一个包含提交哈希的文件):

                  master
                    ↓
A -- B -- C -- D -- E
 \       /
  F --- G  ← feature-1
         \
          H -- I -- J
                    ↑
                feature-2

现在,想象一下我们承诺feature-2分支。我们添加对树的承诺......

         \
          H -- I -- J -- K
                    ↑
                feature-2

…然后我们将分支指针向前移动一位:

         \
          H -- I -- J -- K
                         ↑
                     feature-2

现在,为了理解推送期间发生的情况,我们需要记住远程分支也只是分支,因此只是另一组指针。所以它实际上看起来像这样:

         \
          H -- I -- J ----------- K
                    ↑             ↑
           origin/feature-2    feature-2

我想你可以想象现在推送期间会发生什么:我们告诉远程存储库更新其分支指针,以便它指向K。但服务器只有J,所以我们需要为服务器提供一切来构造可通过以下方式访问的树K(因此其间的任何其他提交,以及这些提交的所有实际内容)。但当然我们不需要用身体去推动J, or H, 甚至A(虽然这些都是技术上 on the feature-2分支,因为你可以reach他们); Git 足够聪明,可以找出哪些对象实际上丢失了(您可以在开始推送时看到 Git 的计算)。

因此,一旦我们将丢失的对象传输到远程存储库,我们就会告诉远程存储库更新其feature-1指针,所以它也将指向K。如果成功,我们还会更新我们的远程分支(origin/feature-2)也指向它(只是为了保持同步)。

现在,合并的情况确实是一样的。想象一下我们合并了master into feature-2 (using git merge master开启时feature-2):

                  master
                    ↓
A -- B -- C -- D -- E -----
 \       /                 \
  F --- G  ← feature-1      \
         \                   \
          H -- I -- J -- K -- L
                              ↑
                          feature-2

现在,如果我们想推动feature-2,我们再次需要向远程存储库提供它没有的所有对象。由于我们现在正在进行合并提交,因此我们需要检查all家长:所以如果服务器没有K我们需要推动K;而且,如果没有E,我们必须推动E。当然,我们需要再次跟踪这些父对象,以确保所有对象都存在于遥控器上。一旦完成,我们只需再次告诉远程设备更新分支指针。

总结一下:一个分支contains所有可以通过在非循环树中导航其提交的父级来访问的提交。但即使这意味着分支通常非常“大”(就历史长度而言),Git 也只会将这些对象传输到它没有的远程存储库。因此,尽管合并可以向分支添加更多提交,但如果远程已经从另一个分支知道这些提交,则不一定必须传输这些提交。


最后,关于变基的最后几句话:上面我们做了git merge master合并master分支到feature-2。如果我们这样做了git rebase master相反,完整的树现在看起来像这样:

                  master               feature-2
                    ↓                      ↓
A -- B -- C -- D -- E -- H' -- I' -- J' -- K'
 \       /
  F --- G  ← feature-1
         \
          H -- I -- J -- K
                         ↑
                  origin/feature-2

如您所见,有新的提交H', I', J' and K'。这些是重写的提交,以便它们从E (where master在变基时指向)而不是G。由于我们重新调整基础,因此没有合并提交L。如上所述,原来的提交仍然存在。只是没有剩下的指针指向它们;因此它们会“丢失”并最终被垃圾收集。

那么现在推的时候有什么问题呢?远程分支仍然指向原来的分支K,但我们希望它指向K'现在。因此,我们开始为远程存储库提供它所需的所有对象,就像以前一样。但是当我们告诉它设置更新分支指针时,它会拒绝这样做。原因是通过将指针设置为K'它必须“回到历史”并忽略提交的存在H to K。它不知道我们已经重新设置了这些基础,并且重写后的内容和原始内容之间也没有联系。所以为了防止意外的数据丢失,远程会拒绝更新分支指针。

现在你可以力推分支。这将告诉远程存储库更新分支指针,即使这样做会丢弃那些原始提交。所以你这样做,情况会是这样的:

                                   origin/feature-2
                  master               feature-2
                    ↓                      ↓
A -- B -- C -- D -- E -- H' -- I' -- J' -- K'
 \       /
  F --- G  ← feature-1

到目前为止,一切都很好:您决定对分支进行变基,并告诉远程存储库接受该分支而无需质疑它。但现在想象我想要pull那;我的分支仍然指向I。因此,运行 pull 与反向推送的作用相同:遥控器为我提供完成历史记录所需的所有对象,然后它告诉我在哪里设置分支指针。那时,我的本地 Git 拒绝这样做,原因与远程存储库之前这样做的原因相同。

通过之前的推送,我们知道我们想要替换原来的提交;但对于拉动,我们就没有这样的能力,所以我们现在需要调查或四处询问,我们是否应该更换本地分支,或者远程是否确实存在一些故障。如果我们在本地自己做一些工作,而我们现在想要合并,情况会变得更糟。

这些问题发生在每个曾经获取过这些原始提交的人身上。一般来说,您希望完全避免这种混乱,因此规则是永远不要对已经发布的内容进行 rebase。只要没有其他人获得这些原始提交,您就可以进行变基,但是一旦这种情况不再存在,那么对于所有相关人员来说,这将是一团糟。所以合并绝对是首选。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GIT rebase 需要重新提交更改 的相关文章

随机推荐