从 git repo 的特定远程分支上的旧提交中删除一些文件(无需推送到 master 分支)

Remove a number of files from old commits on specific remote branch of git repo (without having to push to master branch)

我使用一个由许多人共享的代码库,并且有一个特定的分支仅供我个人使用。我犯了一个大错误,大约 10 次提交前从 git 忽略中删除了一个特定的文件类型,然后将一些文件(加起来占用了大量内存)推送到我个人分支的远程。现在我们的 repo 占用了大量内存,我需要以某种方式从过去的提交中删除这些文件。我已经将文件类型添加回 git 忽略并删除文件以供将来提交,现在我只需要删除过去的提交。

我做了一些研究,知道我有 git filter-branch 和 git filter-repo 等选项,而其他解决方案似乎只适用于修改一次提交。我不想使用 git filter-branch 因为我已经看到很多关于它的警告。我已经尝试 git filter-repo 但我想我误解了如何将我的更改仅推送到我想更改的分支(不必将它们合并到或影响我无法推送到的主分支).如果有一个简单的解决方案涉及编辑单个提交也可以。另请注意,这不是一个大文件,而是我需要删除的许多 (10-20) 个文件(存在于几个不同的路径中)。

我希望解决方案看起来像这样:检查我想更改的分支 > 运行 某种 git 命令从该分支中​​删除文件或更改特定的提交(如果我可以编辑 git 忽略那些提交会很容易)> 将这些更改推送到 那个特定分支的远程版本

结果是我已经成功地从这个分支的远程版本上的旧提交中删除了文件,从而减少了我们存储库的整体大小。

这对我来说是一个巨大的错误,感谢任何和所有建议!

鉴于问题仅出在您自己的分支上,并且尚未在其他任何地方合并,我相信 re-writing 您自己的分支是最简单的操作过程。假设您的 git log --oneline 看起来类似于:

db759dd Refactor ...
ed7e3cc Update ...
fff1234 Fix .gitignore and delete unwanted files # The FIX
314fc46 Update ...
fea0230 Refactor ...
d9fdf5d Update ...
74249a2 Increase ...
c985a1c Fix ...
d94122f Add ...
bad9999 Update .gitignore and add big files # The ISSUE
3a284fb Increase ...
abc1234 Merge PR 1234: Increase number of threads # BRANCH START
...

在上面的示例中,提交 ID abcd123 表示您在创建分支时分支的提交。 Commit bad9999 表示问题提交 ID,fff1234 表示包含修复的提交 ID。签出分支后,您想通过指定分支的提交(或在问题提交 之前 发生的任何后续提交)来进行交互式变基,如下所示:

git rebase -i abc1234

现在您将看到一个 TODO 列表,它将显示所有 (non-merge) 提交 在您指定的 之后,以相反的顺序,如下所示:

pick 3a284fb Increase ...
pick bad9999 Update .gitignore and add big files
pick d94122f Add ...
pick c985a1c Fix ...
pick 74249a2 Increase ...
pick d9fdf5d Update ...
pick fea0230 Refactor ...
pick 314fc46 Update ...
pick fff1234 Fix .gitignore and delete unwanted files
pick ed7e3cc Update ...
pick db759dd Refactor ...

Tip: while doing an interactive rebase, if you change your mind and decide to cancel it, you must first delete all the lines in the file (or at least all the ones with instructions such as "pick"), and then save, and exit. If you simply save and exit without first deleting the lines, you will still proceed with the rebase (which might end up having no effect if your branch was linear, but it's not worth hoping for this is you really intend to cancel it).

现在你要做出决定了。您是否可以简单地删除 ISSUE 提交,如果可以,也删除 FIX 提交是否有意义?如果你能做到这一点,请将 ISSUE 和 FIX 行上的单词“pick”更改为“d”(表示“drop”,或者你可以完全删除该行!),如下所示:

pick 3a284fb Increase ...
d bad9999 Update .gitignore and add big files
pick d94122f Add ...
pick c985a1c Fix ...
pick 74249a2 Increase ...
pick d9fdf5d Update ...
pick fea0230 Refactor ...
pick 314fc46 Update ...
d fff1234 Fix .gitignore and delete unwanted files
pick ed7e3cc Update ...
pick db759dd Refactor ...

如果 ISSUE 提交中还有其他您想保留的更改,那么您(可能1)可以进行更改而不是完全删除它来修复错误的提交是简单地向上移动 FIX 提交并将其压缩到 ISSUE 提交中,如下所示:

pick 3a284fb Increase ...
pick bad9999 Update .gitignore and add big files
s fff1234 Fix .gitignore and delete unwanted files
pick d94122f Add ...
pick c985a1c Fix ...
pick 74249a2 Increase ...
pick d9fdf5d Update ...
pick fea0230 Refactor ...
pick 314fc46 Update ...
pick ed7e3cc Update ...
pick db759dd Refactor ...

注意“s”与“挤压”相同,您总是“向上”挤压到之前选择的提交,因此这会将这 2 个提交挤压在一起。如果 FIX 提交撤销了 ISSUE 提交所做的一些更改,这些更改将取消并且不会出现在新创建的提交 2 中。现在保存并退出,你的变基将开始。随着变基的进行,它会在压缩后暂停并提示您修改新压缩提交的提交消息。在您编写新的提交消息并保存并退出后,rebase 将继续。

rebase 完成后,查看提交以确保您对它们满意,然后强制推出您的分支:

git push --force-with-lease

现在你的大错误提交应该从回购历史中消失,所有新的克隆都不会包含它们。它们可能仍会无限期地保留在服务器上,如果您知道提交 ID,甚至可以通过 Web UI 进行引用,如果这对您来说是个问题,两个典型的选择是询问回购主机的支持团队是否他们可以为您清除服务器上的孤立提交,或者,您可以删除并 re-upload 影响最小的回购协议,因为只有大约 10 个提交 ID 被清除。在删除和 re-pushing 回购之前,我会与支持人员确认您不必重做所有安全设置。

备注:

1 如果 FIX 提交包含的不仅仅是其中的修复,并且如果其他内容需要 ISSUE 和 FIX 之间的提交,那么您将拥有冲突在这里。冲突是生活中的一个事实,你只需要解决它们。 (幸运的是,它们通常 straight-forward 可以解决,尤其是在您编写了冲突代码的两边的情况下。)

2 如果 FIX 提交与 ISSUE 提交完全相反(例如,如果您通过还原 ISSUE 创建了 FIX),那么新的压缩提交甚至不会created- 它只会跳过它,你的新分支历史将少 2 个提交,就好像两者都不存在一样。如果这适用,您也可以简单地删除 rebase TODO 列表中的提交。