[原创] 如何从 Git 的提交历史记录中删除大文件

1. 概述

在本教程中,我们将学习如何使用各种工具从 git 存储库的提交历史记录中删除大文件。

2. 使用*git filter-branch*

这是最常用的方法,它可以帮助我们重写提交分支的历史记录。

例如,假设我们错误地将一个 blob 文件放入项目文件夹中,删除它后,我们仍然会在 git 历史记录中注意到该文件:

$ git log --graph --full-history --all --pretty=format:"%h%x09%d%x20%s"
* 9e87646        (HEAD -> master) blob file removed
* 2583677        blob file
* 34ea256        my first commit

我们可以通过使用以下命令重写树及其内容来从 git 历史记录中删除 blob 文件:

$ git filter-branch --tree-filter 'rm -f blob.txt' HEAD

在这里,rm选项从树中删除文件。此外,如果我们项目中的其他提交目录中不存在该文件,则-f 选项可防止命令失败。如果没有-f 选项,当我们的项目中有多个目录时,该命令可能会失败。

这是我们运行命令后的 git 日志:

* 8f39d86        (HEAD -> master) blob file removed
* e99a81d        blob file
| * 9e87646      (refs/original/refs/heads/master) blob file removed
| * 2583677      blob file
|/  
* 34ea256        my first commit

我们可以用提交历史的 SHA1 密钥替换 HEAD,以尽量减少重写。

我们的 git log 仍然包含对已删除文件的引用。我们可以通过更新我们的 repo 来删除引用:

$ git update-ref -d refs/original/refs/heads/master

-d选项验证它仍包含旧值后,删除指定的裁判。

我们需要在存储库中记录我们的引用更改:

$ git reflog expire --expire=now --all

到期子李子年长参考日志条目。

最后,我们需要清理和优化我们的 repo:

$ git gc --prune=now

-prune =现在选择梅干不论其年龄的散装物品。

运行命令后,这是我们的 git 日志:

* 6f49d86        (HEAD -> master) my first commit

我们可以看到 refs 已被删除。

或者,我们可以运行:

$ git filter-branch --index filter 'git rm --cached --ignore-unmatched blob.txt' HEAD

这与tree-filter完全一样 但它更快,因为它只重写索引,即工作目录。如果文件从我们项目中的其他提交目录中丢失,子命令–ignore-unmatched可防止命令失败。

我们应该注意,在删除大文件时,这种使用两个不同命令的方法可能会很慢。

3. 使用*git-filter-repo*

另一种方法是使用git-filter-repo命令。它是第三方附加组件,使用起来更简单,而且比其他方法更快。而且是git官方文档中推荐的方案。

3.1. 安装

它至少需要 python3 >= 3.5 和 git >= 2.22.0;某些功能需要 git 2.24.0 或更高版本

我们将在我们的 Linux 机器上安装git-filter-repo。对于 Windows 安装指南,我们可以参考文档

首先,我们将使用以下命令安装python-pipgit-filter-repo

$ sudo apt install python3-pip
$ pip install --user git-filter-repo

或者,我们可以使用以下命令安装git-filter-repo

# Add to bashrc.
export PATH="${HOME}/bin:${PATH}"

mkdir -p ~/bin
wget -O ~/bin/git-filter-repo https://raw.githubusercontent.com/newren/git-filter-repo/7b3e714b94a6e5b9f478cb981c7f560ef3f36506/git-filter-repo
chmod +x ~/bin/git-filter-repo

3.2. 删除文件

让我们运行命令来检查我们的 git 日志:

$ git log --graph --full-history --all --pretty=format:"%h%x09%d%x20%s"
* ee36517        (HEAD -> master) blob.txt removed
* a480073        project folder

接下来我们要分析我们的 repo:

$ git filter-repo --analyze
Processed 5 blob sizes
Processed 2 commits
Writing reports to .git/filter-repo/analysis...done.

这将生成我们的回购状态报告目录。该报告可以在 .git/filter-repo/analysis 找到。这些信息可能有助于确定在后续运行中要过滤的内容。它还可以帮助我们确定我们之前的过滤命令是否真的做了我们想要它做的事情。

然后,让我们使用选项–path-match运行此命令这有助于指定要包含在过滤历史记录中的文件:

$ git filter-repo --force --invert-paths --path-match blob.txt

这是我们的新 git 日志:

* 8940776        (HEAD -> master) project folder

执行后,它将更改修改后的提交的提交哈希。

4. 使用 BRG Repo-Cleaner

另一个不错的选择是BRG Repo-Cleaner,它是用 Java 编写的第三方插件。

它比*git filter-branch*方法更快。此外,它适用于删除大文件、密码、凭据和其他私人数据

假设我们要删除大于 200MB 的 blob 文件。这个插件可以很容易地做到这一点:

$ java -jar bfg.jar --strip-blob-bigger-than 200M my-repo.git

然后,让我们运行这个命令来清理死数据:

$ git gc --prune=now --aggressive

5. 使用*git-rebase*

我们需要 git 日志中的 SHA1 密钥才能使用这种方法:

$ git log --graph --full-history --all --pretty=format:"%h%x09%d%x20%s"
* 535f7ea        (HEAD -> master) blob file removed
* 8bffdfa        blob file
* 5bac30b        index.html

我们的目标是从我们的提交历史中删除 blob 文件。因此,我们将使用要删除的条目之前条目历史记录中的 SHA1 密钥。

使用此命令,我们进入交互式变基:

$ git rebase -i 5bac30b

这将打开我们的nano编辑器,显示:

pick 535f7ea blob file removed
pick 8bffdfa blob file 

# Rebase 5bac30b..535f7ea onto 535f7ea (2 command)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .  create a merge commit using the original merge commit's
# .  message (or the oneline, if no original merge commit was
# .  specified). Use -c <commit> to reword the commit message.

现在,我们将通过删除文本“ pick 535f7ea blob file removed ”来修改它。这有助于我们更改提交历史并删除我们之前删除的历史。

然后我们保存文件并退出编辑器,它会将我们带到终端并显示以下消息:

interactive rebase in progress; onto 535f7ea
Last command done (1 command done):
pick 535f7ea blob file removed
No commands remaining.
You are currently rebasing branch 'master' on '535f7ea'.
(all conflicts fixed: run "git rebase --continue")

最后,让我们继续 rebase 操作:

$ git rebase --continue
Successfully rebased and updated refs/heads/master.

然后我们可以验证我们的提交历史:

$ git log --graph --full-history --all --pretty=format:"%h%x09%d%x20%s"
* 5bac30b        (HEAD -> master) index.html

我们应该注意到这种方法不如*git-filter-repo***快**。

六,结论

在本文中,我们学习了从 git 存储库的提交历史记录中删除大文件的不同方法。我们还看到,根据 git 文档,推荐使用git filter-repo,因为与其他方法相比,它速度快且缺点更少。

版权声明:
作者:感冒的梵高
链接:https://www.techfm.club/p/27062.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>