Git - 从已合并的分支中移除提交记录

3

我不小心提交了一些巨大的文件,然后撤销了该提交。但是这会导致在拉取此分支的任何人都需要在历史记录中获取这些文件,因此我决定删除或压缩这两个提交。但是,一些分支已经被合并。我不知道如何使 "git rebase -i" 保持分支结构。

现在的历史记录看起来像:

H - new commits
|
G - merge
| \
|  F - commits on another branch
|  |
E  | - some other commits
|  |
D  | - corrected B
|  |
C  | - revert B
|  |
B  | - huge files
| /
A - early commit

我可以将其更改为以下内容吗?

h - new commits
|
g - merge
| \
|  F - commits on another branch
|  |
e  | - some other commits
|  |
d  | - corrected B
| /
A - early commit

让另一方重新合并是否可行? - Tim Biegeleisen
@TimBiegeleisen 是的,但必须保持结构。 - Xiao
交互式变基并删除“巨大文件”和“还原B”。然后重新执行合并。最后,挑选在此之后的新提交。 - Tim Biegeleisen
1
@TimBiegeleisen @nonsensickle 谢谢。git filter-branch 帮助节省了空间。虽然还没有完全弄清楚如何使用它完全删除提交,但对于这种情况已经足够了。 - Xiao
@nonsensickle,看到你的回答了,谢谢。 - Xiao
显示剩余4条评论
2个回答

2

是的,你可以,但你不应该这样做。

这将要求你重写历史并替换服务器上已经推送的历史记录(这需要强制推送,往往会导致所有人都对你大喊大叫)

但如果你真的想这样做,git filter-branch就是你想要使用的工具,就像这个SO答案中所描述的那样。因此,你可以这样做:

git filter-branch --commit-filter '
    if [ "$GIT_COMMIT" = "<your commit to remove here>" ]
    then
        skip_commit "$@";
    else
        git commit-tree "$@";
    fi'  HEAD

这里还有一些例子,请点击这里查看。

太好了,这正是我要找的。这是一个内部仓库,让其他人进行强制拉取不是问题。 - Xiao

0

不行,你不能这样做。

每个提交的哈希值不仅包括索引中所有文件的哈希内容,还包括提交的父级的哈希值。

“更正的B”将有一个与现在不同的父级。这将改变哈希值。

虽然可以修复此问题,但无法避免强制推送修复并让每个人强制拉取它。

唯一真正解决此问题的方法是以下过程:

 git checkout A

在分支派生之前,检查父提交。然后创建两个工作分支:

 git checkout -b corrected-mainline
 git checkout -b corrected-fork

您现在位于已更正的分支上。现在,在此分支上,您应该能够git cherry-pick所有提交,直到F提交,跳过具有巨大文件及其还原的提交。如果其中任何提交是合并,请执行相同的合并。

现在,在corrected-mainline分支上执行相同操作。

 git checkout corrected-mainline

现在,使用git cherry-pick命令挑选主干分支上的所有提交,直到G合并之前的最后一个提交。然后,使用corrected-fork分支进行合并。此时,这就是您更正后的G合并提交。
继续挑选图表中原本在G上方的任何提交,直到原来分支上的最后一个提交为止。
此时,您的工作分支的内容应与原始分支的内容相同。请验证是否如此。
然后,删除原始分支,将工作分支重命名为原始分支的名称。或者,使用git reset --hard将原始分支重置为已更正的工作分支。
然后使用git push --force命令将更正的分支推送上去。当然,任何拉取该分支的人最终都会得到强制拉取。

我正在使用 git filter-branch。感谢您的回答。 - Xiao

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