【问题标题】:How to remove all commits of a topic Git branch?如何删除主题 Git 分支的所有提交?
【发布时间】:2014-08-06 09:23:59
【问题描述】:

假设我有以下历史:

   A---B---C----------D------------E master
            \         /\         /
            W1--X1--Y1 W2--X2--Y2 
                  topic1      topic2

是否可以按照以下方式删除所有主题分支及其提交

A-B-C-D-E master

【问题讨论】:

  • 我假设 D 和 E 是合并提交?您想保留 W1-Y2 所做的更改吗?

标签: git git-rewrite-history git-branch-sculpting


【解决方案1】:

您有几种选择。

解决方案 1:Squash 合并

一种解决方案是简单地使用硬重置和一些壁球合并:

git checkout master
git reset --hard C

git merge --squash topic1
git commit -m "Rewrite D"

git merge --squash topic2
git commit -m "Rewrite E"

# Verify that the new branch is no different from the old one
git diff sha_of_old_E

这里的想法是,壁球合并会将主题分支的最终状态(即最后一次提交)复制到您当前的工作副本中,然后您可以在其中提交它。它有效地将一个分支压缩成一个提交。

文档

解决方案 2:交互式变基

另一种方法是使用交互式 rebase 将主题分支压缩为单个提交。首先,调用变基

git rebase -i C

这将在您的终端中打开交互式变基 TODO 列表编辑器。您将看到显示以下提交:

pick sha W1
pick sha X1
pick sha Y1
pick sha W2
pick sha X2
pick sha Y2

您想要做的是类似于上面的壁球合并。您可以将主题分支压缩为单个提交,因此对于主题分支的每个提交,将后代提交压缩(或“修复”)到其父级:

pick sha W1
squash sha X1
squash sha Y1
pick sha W2
squash sha X2
squash sha Y2

然后在 Vim 编辑器中点击 :wq 开始交互式变基。我不会详细介绍接下来的步骤,因为它们已经在互联网上的其他众多来源中进行了充分详细的介绍,例如 Pro Git § 6.4 Git Tools - Rewriting History - Squashing Commits

您可能需要通过使用简单的 diff 验证新重写的分支与前一个分支没有什么不同,从而再次检查您是否正确执行了 rebase:

git diff sha_of_old_E

请注意,如果您不想为每个 squash 编辑提交消息,则可以使用“fixup”,它只会重复使用上一次提交的提交消息:

pick sha W1
fixup sha X1
fixup sha Y1
pick sha W2
fixup sha X2
fixup sha Y2

请注意,您也可以分别使用 sf 进行 squash 和 fixup。

文档

强制推送警告

请注意,当然,上述两种解决方案都会重写您的提交历史记录,因此您的新提交将具有不同的 sha ID。如果您已经将旧版本的分支推送到远程,那么您需要强制推送以覆盖旧副本。如果您与其他人共享您的分支,这可能不是您想要做的事情,原因我不会在这里详述,因为在许多其他在线资源中都有详细记录强制推送的可能危险,例如:

【讨论】:

    【解决方案2】:

    一个技巧是把clone a single branch从那个repo变成一个新的repo

    git clone <url> --branch <branch> --single-branch [<folder>]
    

    并从那里使用新的 repo。

    【讨论】:

      【解决方案3】:

      您可以使用交互式变基:

      git rebase -i <hash of A>
      

      然后通过删除引用提交的行来删除您不想要的提交。你会得到类似的东西:

      pick <hash of B> message of B
      pick <hash of C> message of C
      pick <hash of W1> message of W1
      pick <hash of X1> message of X1
      pick <hash of Y1> message of Y1
      pick <hash of D> message of D
      pick <hash of W2> message of W2
      pick <hash of X2> message of X2
      pick <hash of Y2> message of Y2
      pick <hash of E> message of E
      

      然后像这样删除那些引用主题分支的行:

      pick <hash of B> message of B
      pick <hash of C> message of C
      pick <hash of D> message of D
      pick <hash of E> message of E
      

      【讨论】:

      • 没有投反对票,但请注意合并提交 D 和 E 实际上不会与您使用的交互式 rebase 命令一起显示。不仅如此,从交互式变基编辑器中删除提交通常意味着您将丢弃这些提交中的更改,这样它们就不会保留在任何后代中。这肯定不是你或提问者真正想要的,不是吗?您是否真的尝试过自己运行上述命令,看看会发生什么?
      • @Cupcake 用remove all topic branches and their commits这句话我明白他想放弃这些更改,并且在问题中没有写到 D 和 E 是合并提交,但是是的,也许我应该假设.如果我误解了这个问题,我很抱歉,并不是要伤害回答者。
      • 您可以在提交图中看到,提问者给出的 D 和 E 是合并提交。
      猜你喜欢
      • 2020-09-08
      • 2022-10-15
      • 1970-01-01
      • 1970-01-01
      • 2016-07-20
      • 2016-12-29
      • 2014-02-22
      • 2020-01-07
      • 2016-01-09
      相关资源
      最近更新 更多