git rebase已经合并的分支?

13

我从主分支创建了一个特性分支。然后在特性分支上有一个提交 [F1]。

        [F1]            -- Feature Branch
       /
[M1]-[M2]               -- Master Branch

在此之后,功能分支被合并到主分支中,主分支中增加了两个提交[M3]和[M4]。

        [F1]                   -- Feature Branch
       /    \
[M1]-[M2]-[F1]-[M3]-[M4]       -- Master Branch

现在我向特性分支添加了两个更多的提交。

        [F1]-[F2]-[F3]         -- Feature Branch
       /   \
[M1]-[M2]-[F1]-[M3]-[M4]       -- Master Branch

现在,我应该先将特性分支变基到主分支,这样特性分支就有了[M3]和[M4]的更改提交,还是直接进行Git合并。

另外,如果我先执行git rebase,[F1]提交会不会在两个分支中都存在:

                       [F1]-[F2]-[F3]       -- Feature Branch
                       /
[M1]-[M2]-[F1]-[M3]-[M4]                    -- Master Branch
3个回答

5
如果您尚未对主分支进行更改,并且不介意重写主分支的历史记录,那么有一种方法可以做到这一点 - 但是在变基时,您正在重写历史记录,因此请确保您首先知道自己在做什么
如果您确定这是您要采取的历史记录方向,则应从 feature 被切出的提交(在您的情况下为 [M2] )开始检出 master 分支并交互式地变基它( git rebase-i )。
在重新设置之前,您的历史记录应如原始问题所示:
        [F1]-[F2]-[F3]         -- Feature Branch
       /   \
[M1]-[M2]-[F1]-[M3]-[M4]       -- Master Branch

一旦您开始交互式变基,您应该看到以下操作:

pick hash_f1 [F1]
pick hash_m3 [M3]
pick hash_m4 [M4]

你需要放弃第一个提交,即[F1],以便在没有该提交的情况下重播feature在提交[F2][F3]之前合并的内容,使master可以重播这些更改。请注意,你不会失去[F1]提交,因为它仍将存在于feature的历史记录中。
变基应该给你这个历史记录:
        [F1]-[F2]-[F3]         -- Feature Branch
       /
[M1]-[M2]-[M3]-[M4]            -- Master Branch

master拥有所有M提交,feature拥有所有F提交,仍从[M2]剪切。从那里开始,只需简单合并即可将feature合并回master:

git merge --no-ff feature

然后你就得到了你想要的结果:

        [F1]-[F2]-[F3]         -- Feature Branch
       /             \
[M1]-[M2]-[M3]-[M4]-[F*]       -- Master Branch

请谨慎考虑是否需要重写历史记录,因为这可能存在风险。但是,在本地执行此操作绝对是值得的。

此外,可以将此过程扩展到任何引用,而不仅仅是功能和主分支,因此在其他情况下可能更合理。在我看来,像master这样的稳定分支通常不应该被重写其历史记录,但每个 Git 环境和工作流程都不同,因此真的没有不能被重写的规则。


2
您不必进行变基操作,只需执行合并操作即可。变基可以创建一个非常清晰的历史记录,但实际上它并不能真正地代表历史事件。合并更加安全,更直接,并且可以真实地反映开发人员的操作。
从其他版本控制系统转到git的人们通常不喜欢git复杂的分支和合并历史记录,因此他们中的一些人会过度使用变基功能。这需要额外的努力,失败率比“合并”更高,并且会导致错误的历史视图。
我并不是说您永远不应该使用变基,但作为经验法则,我建议默认情况下使用“合并”,只有当您真正想改写历史时才使用变基。
变基有用的一个例子是:假设您正在进行许多增量提交,并在本地存储库中添加和撤消内容。在推送到全局存储库之前,您决定希望其他团队成员将您的贡献视为一个更干净、单一的提交,去除所有无关紧要的内容。然后您可以使用“交互式变基”来整合提交并改进提交消息,然后再推送。

7
这根本没有回答问题。我理解你的观点,虽然我不同意,但它只是你的观点。这样做不是回答问题,而是回避回答问题。 - Lazar Ljubenović
1
我认为它直接回答了原文中的一个问题:“我应该先将特性分支变基到主分支,以便特性分支具有[M3]和[M4]提交的更改,还是应该直接进行git合并?” 我同意你的看法,它没有回答第二个问题。 - Adi Levin
很抱歉要这么说,但我认为这是一个非常误导性的答案,基于你个人的偏好而不是实际价值。否定变基就像丢掉 Git 中最强大和有用的功能之一。将基础分支合并到特性分支中会产生多余的合并提交和混乱的提交历史,难以跟踪。 - Chris Kobrzak
2
@Chris 在这个回答中,Adi 什么时候“否决变基”了?他甚至明确表示“我并不是说你永远都不应该使用变基”,并且提供了一个变基很有用的例子!是的,这个回答中有一些观点(就像你认为合并“很混乱”一样),但他清楚地表明这是他的观点和他的“经验法则”等,并且还阐述了另一种观点。我不确定你是否正确地阅读了这个回答,否则你想要什么。 - ChrisM

2

正如所述,无需进行rebase操作。

针对问题的最后一部分:

"如果我先执行git rebase,那么[F1]提交不会在两个分支中都存在吗?"

如果您继续进行rebase操作,F1提交将被省略。

根据https://git-scm.com/docs/git-rebase的说明:

如果上游分支已经包含了您所做的更改(例如,因为您发送了一个补丁并被上游接受),那么该提交将被跳过。例如,在以下历史记录上运行git rebase master(其中A'和A引入了相同的更改集,但具有不同的提交者信息):

      A---B---C topic
     /
D---E---A'---F master

会导致:
               B'---C' topic
              /
D---E---A'---F master

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接