在导入具有多年历史的Subversion存储库后,我遇到了与许多二进制资产相关的类似问题。 在git: shrinking Subversion import中,我描述了如何将我的git存储库从4.5 GiB缩减到大约100 MiB。
假设您想要从“Delete media files” (6fe87d)中删除的文件从所有提交中删除,并使其适应于您的repo,请参考我的博客文章中的方法:
$ git filter-branch -d /dev/shm/git --index-filter \
"git rm --cached -f --ignore-unmatch media/Optika.1.3.?.*; \
git rm --cached -f --ignore-unmatch media/lens.svg; \
git rm --cached -f --ignore-unmatch media/lens_simulation.swf; \
git rm --cached -f --ignore-unmatch media/v.html" \
--tag-name-filter cat --prune-empty -- --all
您的GitHub repo没有任何标签,但我包括了一个标记名称过滤器,以防您有私有标签。
git filter-branch
文档涵盖了--prune-empty
选项。
--prune-empty
某些类型的过滤器会生成不会更改树的空提交。此选项允许git-filter-branch
忽略这样的提交...
使用此选项意味着您重新编写的历史记录将不包含“Delete media files”提交,因为它不再影响树。在新历史记录中从未创建媒体文件。
此时,由于文档记录的行为,您的存储库中会出现重复。
如果原有的引用与改写后的不同,将会存储在命名空间refs/original/
中。
如果您对新重写的历史记录满意,则可以删除备份副本。
$ git for-each-ref --format="%(refname)" refs/original/ | \
xargs -n 1 git update-ref -d
Git非常注意保护您的工作,因此即使进行了所有这些有意的重写和删除,reflog仍然保留旧提交。使用以下两个命令序列清除它们:
$ git reflog expire --verbose --expire=0 --all
$ git gc --prune=0
现在您的本地存储库已准备好,但您需要将更新推送到GitHub。您可以逐个更新它们。例如,对于一个名为master的本地分支,您可以运行以下命令:
$ git push -f origin master
假设您不再拥有名为issue5的本地分支。您的克隆仍然有一个称为origin/issue5的引用,跟踪其在GitHub存储库中的位置。运行git filter-branch
也会修改所有的origin引用,因此您可以更新GitHub而无需分支。
$ git push -f origin origin/issue5:issue5
如果所有本地分支与其在GitHub端的相应提交匹配(即没有未推送的提交),则可以执行批量更新。
$ git for-each-ref --format="%(refname)" refs/remotes/origin/ | \
grep -v 'HEAD$' | perl -pe 's,^refs/remotes/origin/,,' | \
xargs -n 1 -I '{}' git push -f origin 'refs/remotes/origin/{}:{}'
第一阶段的输出是一个引用名列表:
$ git for-each-ref --format="%(refname)" refs/remotes/origin/
refs/remotes/origin/HEAD
refs/remotes/origin/issue2
refs/remotes/origin/issue3
refs/remotes/origin/issue5
refs/remotes/origin/master
我们不想要 HEAD 伪参考,并使用 grep -v
去掉它。对于其余的内容,我们使用 Perl 来剥离 refs/remotes/origin/
前缀,并针对每一个运行以下形式的命令:
$ git push -f origin refs/remotes/origin/BRANCH:BRANCH
其中 BRANCH 是指以下分支名之一:
- section_merge
- side-media-icons
- side-pane-splitter
- side-popup
- v2
git merge
吗? - Chris Frederick