假设你的 git 历史记录如下所示:

1 2 3 4 5

1-5 是单独的修订。您需要删除 3,同时保留 1、2、4 和 5。如何才能做到这一点?

当要删除的修订之后有数百个修订时,有没有一种有效的方法?

有帮助吗?

解决方案

要将修订版 3 和修订版 4 合并为一个修订版,您可以使用 git rebase。如果要删除修订版 3 中的更改,则需要在交互式 rebase 模式下使用 edit 命令。如果您想将更改合并到一个版本中,请使用squash。

我已经成功地使用了这种挤压技术,但以前从未需要删除修订版。“拆分提交”下的 git-rebase 文档有望为您提供足够的想法来解决这个问题。(或者其他人可能知道)。

来自 git 文档:

从您想要按原样保留的最旧的提交开始:

git rebase -i <after-this-commit>

编辑器将启动当前分支中的所有提交(忽略合并提交),这些提交是在给定提交之后进行的。您可以根据自己的喜好重新排序此列表中的提交,也可以删除它们。该列表看起来或多或少像这样:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

单行描述纯粹是为了您的愉悦;git-rebase 不会查看它们,而是查看提交名称(本例中为“deadbee”和“fa1afe1”),因此不要删除或编辑这些名称。

通过将命令“pick”替换为命令“edit”,您可以告诉 git-rebase 在应用该提交后停止,以便您可以编辑文件和/或提交消息、修改提交并继续变基。

如果要将两个或多个提交合并为一个,请将第二次及后续提交的命令“pick”替换为“squash”。如果提交有不同的作者,它将把压缩的提交归因于第一个提交的作者。

其他提示

这是一种以非交互方式删除特定内容的方法 <commit-id>, ,只知道 <commit-id> 您想要删除:

git rebase --onto <commit-id>^ <commit-id> HEAD

这条评论 (并且我检查了这是真的),rado 的答案非常接近,但使 git 处于分离的头部状态。相反,删除 HEAD 并用它来删除 <commit-id> 从您所在的分支:

git rebase --onto <commit-id>^ <commit-id>

如前所述 git-rebase(1) 是你的朋友。假设提交在你的 master 分支,你会这样做:

git rebase --onto master~3 master~2 master

前:

1---2---3---4---5  master

后:

1---2---4'---5' master

来自 git-rebase(1):

还可以通过折断来删除一系列提交。如果我们有以下情况:

E---F---G---H---I---J  topicA

然后命令

git rebase --onto topicA~5 topicA~3 topicA

将导致删除提交F和G:

E---H'---I'---J'  topicA

如果F和G以某种方式存在缺陷,或者不应该成为主题的一部分,这将很有用。请注意,与 - to和参数的参数可以是任何有效的commit-ish。

如果您只想删除修订版 3 中所做的更改,您可能需要使用 git revert。

Git revert 只是创建一个新的修订版本,其中的更改会撤消您要恢复的修订版本中的所有更改。

这意味着您保留有关不需要的提交和删除这些更改的提交的信息。

如果有人同时从您的存储库中提取数据,这可能会更加友好,因为恢复基本上只是一个标准提交。

到目前为止的所有答案都没有解决尾随的问题:

当要删除该修订后数百个修订时,是否有有效的方法?

步骤如下,但为了参考,我们假设以下历史记录:

[master] -> [hundreds-of-commits-including-merges] -> [C] -> [R] -> [B]

C:在要删除的提交之后提交(干净)

:要删除的提交

:就在要删除的提交之前的提交(基础)

由于“数百次修订”的限制,我假设以下先决条件:

  1. 有一些令人尴尬的承诺,你希望它永远不存在
  2. 有零个后续提交实际上依赖于该令人尴尬的提交(恢复时零冲突)
  3. 您不在乎您将被列为数百个干预提交的“提交者”(“作者”将被保留)
  4. 您从未共享过存储库
    • 或者你实际上对所有曾经克隆历史并做出承诺的人有足够的影响力,以说服他们使用你的新历史
    • 你呢 不在乎 关于 改写历史

这是一组相当严格的约束,但有一个有趣的答案实际上适用于这个极端情况。

步骤如下:

  1. git branch base B
  2. git branch remove-me R
  3. git branch save
  4. git rebase --preserve-merges --onto base remove-me

如果确实没有冲突,那么这应该继续进行,不会再有任何中断。如果存在冲突,您可以解决它们并 rebase --continue 或者决定忍受尴尬 rebase --abort.

现在你应该在 master 不再有提交 在里面。这 save 分支指向您之前所在的位置,以防您想要协调。

您想如何安排其他人转移到您的新历史记录取决于您。您需要熟悉 stash, reset --hard, , 和 cherry-pick. 。并且您可以删除 base, remove-me, , 和 save 分支机构

这是我遇到的情况以及我是如何解决的。

[branch-a]

[Hundreds of commits] -> [R] -> [I]

这里 R 是我需要删除的提交,并且 I 是之后的单个提交 R

我做了一个恢复提交并将它们压在一起

git revert [commit id of R]
git rebase -i HEAD~3

在交互式变基压缩期间,最后 2 次提交。

我也遇到了类似的情况。使用以下命令使用交互式变基,并在选择时删除第三次提交。

git rebase -i remote/branch

rado 和 kareem 的答案对我没有任何作用(仅显示消息“当前分支是最新的。”)。发生这种情况可能是因为“^”符号在 Windows 控制台中不起作用。然而,根据 注释,将 '^' 替换为 '~1' 解决了问题。

git rebase --onto <commit-id>^ <commit-id>

要从 git 存储库中删除旧的提交历史记录:

首先在cmd下面运行

rm -rf .git

-- 从当前重新创建仓库

git init                                                                           
git add .                                                  
git commit -m "first commit"

-- 推送到github远程仓库

git remote add origin git@github.com<your git mail>   
git push -u --force origin master
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top