删除由 git 创建的大型. pack 文件

我将大量文件签入到一个分支并合并,然后必须删除它们,现在我只剩下一个大的。我不知道怎么处理的文件。

我使用 git rm -rf xxxxxx删除了所有的文件,我还运行了 --cached选项。

谁能告诉我如何删除目前位于以下目录中的大型.pack 文件:

.git/objects/pack/pack-xxxxxxxxxxxxxxxxx.pack

我只是需要删除分支,我仍然有,但不再使用?还是说我还有别的事要处理?

我不知道有多大区别,但它显示一个挂锁对文件。

谢谢


剪辑

下面是我的 bash _ history 的一些摘录,它们可以帮助我了解我是如何进入这种状态的(假设此时我正在处理一个名为“ my-Branch”的 git 分支,并且我得到了一个包含更多文件夹/文件的文件夹) :

git add .
git commit -m "Adding my branch changes to master"
git checkout master
git merge my-branch
git rm -rf unwanted_folder/
rm -rf unwanted_folder/     (not sure why I ran this as well but I did)

我想我也运行了以下命令,但是它没有出现在 bash _ history 中:

git rm -rf --cached unwanted_folder/

我还认为我运行了一些 git 命令(如 git gc)来尝试整理包文件,但是它们没有出现在。Bash _ history 文件。

167587 次浏览

一种选择是:

手动运行 git gc将一些包文件压缩为一个或几个包文件。 这种操作是持久的(即大型包文件将保留其压缩行为) ,因此使用 git gc --aggressive定期压缩存储库可能是有益的

另一个选项是保存代码和。Git 到某处,然后删除。使用现有代码重新开始,创建一个新的 git 存储库(git init)。

问题是,即使您删除了这些文件,它们仍然出现在以前的版本中。这就是 git 的全部意义所在,即使你删除了一些东西,你仍然可以通过访问历史记录来得到它。

您要做的是重写历史,它涉及到 git filter-branch命令。

在他们的网站上有一个很好的解释

为了更直接地回答您的问题,您基本上需要运行这个命令,相应地将 unwanted_filename_or_folder替换为:

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch unwanted_filename_or_folder' --prune-empty

这将从回购的活动历史中删除对这些文件的所有引用。

下一步,执行 GC 循环,强制对文件的所有引用过期并从包文件中清除。这些命令中不需要替换任何内容。

git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
# or, for older git versions (e.g. 1.8.3.1) which don't support --stdin
# git update-ref $(git for-each-ref --format='delete %(refname)' refs/original)
git reflog expire --expire=now --all
git gc --aggressive --prune=now

场景 A : 如果您的大文件只被添加到一个分支,那么您不需要运行 git filter-branch。您只需删除分支并运行垃圾收集:

git branch -D mybranch
git reflog expire --expire-unreachable=all --all
git gc --prune=all

场景 B : 但是,根据您的 bash 历史记录,您似乎已经将更改合并到 master 中了。如果您还没有与任何人共享更改(还没有 git push)。最简单的事情将是重置主人回到合并之前与分支,有大的文件。这将消除分支的所有提交以及合并后主控的所有提交。因此,除了大文件之外,您可能会丢失您实际想要的更改:

git checkout master
git log # Find the commit hash just before the merge
git reset --hard <commit hash>

然后运行场景 A 中的步骤。

场景 C : 如果合并后 master 上的分支 或者还有其他更改,那么最好对 master 进行重新定位,并选择性地包含您想要的提交:

git checkout master
git log # Find the commit hash just before the merge
git rebase -i <commit hash>

在编辑器中,删除与添加大文件的提交相对应的行,但保持其他内容不变。保存并退出。您的主分支应该只包含您想要的内容,而不应该包含大文件。请注意,没有 -pgit rebase将消除合并提交,因此在 <commit hash>之后,master 的历史记录将是线性的。这对你来说可能是可以的,但是如果不行,你可以尝试用 -p,但是 git help rebasecombining -p with the -i option explicitly is generally not a good idea unless you know what you are doing

然后从方案 A 运行命令。

我有点晚了,但以防上述答案没有解决查询,然后我找到了另一种方式。只需从中删除特定的大文件。收拾行李。我有这个问题,我签入了一个大的2GB 文件意外。我按照这个链接中解释的步骤: http://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/

正如 loganfsmyth 在他的 回答中已经指出的那样,您需要清除 git 历史,因为即使在从回购中删除了这些文件之后,这些文件仍然存在。GitHub 官方文档 推荐大巨巨filter-branch更容易使用:

从历史记录中删除文件

从他们的网站下载 BFG。确保已经安装了 java,然后创建一个镜像克隆并清除历史记录。确保用要删除的文件名替换 YOUR_FILE_NAME:

git clone --mirror git://example.com/some-big-repo.git
java -jar bfg.jar --delete-files YOUR_FILE_NAME some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push

删除文件夹

同上,但使用 --delete-folders

java -jar bfg.jar --delete-folders YOUR_FOLDER_NAME some-big-repo.git

其他选择

BFG 还允许更花哨的选项(见 医生) ,如下:

从历史记录中删除所有大于100M 的文件:

java -jar bfg.jar --strip-blobs-bigger-than 100M some-big-repo.git

重要!

在运行 BFG 时,要注意 YOUR_FILE_NAMEYOUR_FOLDER_NAME实际上只是文件/文件夹名称。它们不是路径,所以像 foo/bar.jpg这样的东西不会工作!相反,所有具有指定名称的文件/文件夹将从回购历史中删除,不管它们存在于哪个路径或分支中。

这是一个比编码更方便的解决方案。压缩文件。以文件视图格式打开 zip (与解压缩不同)。删除。打包文件。解压并替换文件夹。非常有效!

运行以下命令,将 PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA替换为要删除的文件的路径,而不仅仅是文件名。这些论点将:

  1. 强制 Git 处理(但不签出)每个分支和标记的整个历史
  2. 删除指定的文件以及由此产生的任何空提交
  3. 覆盖现有的标记
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --prune-empty --tag-name-filter cat -- --all

这将有力地从回购的活动历史中删除所有对文件的引用。

下一步,执行 GC 循环,强制过期文件的所有引用并从包文件中清除。这些命令中不需要替换任何内容。

git update-ref -d refs/original/refs/remotes/origin/master
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --prune=now

这里使用的是 BFG 就像 GitHub 推荐的那样,与@Timo 的答案相同,只是稍有不同,因为我花了一些时间查看了 CLI 选项。

假设我很久以前使用了超过 60MB的映像,并且无法真正撤消提交。我只需要运行以下命令

java -jar /jarfiles/bfg-1.14.0.jar --delete-files '*.{png,jpg,JPG,PNG}'

然后,我会得到一个建议,即我应该运行以下命令,我将这样做

 git reflog expire --expire=now --all && git gc --prune=now --aggressive

最后,使用

git push --force

您可以验证包文件大小随着

du -sh ./