题
假设你的 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:在要删除的提交之后提交(干净)
右:要删除的提交
乙:就在要删除的提交之前的提交(基础)
由于“数百次修订”的限制,我假设以下先决条件:
- 有一些令人尴尬的承诺,你希望它永远不存在
- 有零个后续提交实际上依赖于该令人尴尬的提交(恢复时零冲突)
- 您不在乎您将被列为数百个干预提交的“提交者”(“作者”将被保留)
- 您从未共享过存储库
这是一组相当严格的约束,但有一个有趣的答案实际上适用于这个极端情况。
步骤如下:
git branch base B
git branch remove-me R
git branch save
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