赞
踩
近期要将git仓库迁移到github中,结果因为记录中包含大文件导致无法上传代码,所以本文来介绍查找和重写 Git 记录的命令:git rev-list, git filter-branch,用来找出大文件并且删除大文件。
首先通过 rev-list
来找到仓库记录中的大文件:
- $ git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '
- /^blob/ {print substr($0,6)}' | awk '$2 >= 25*1024^2' | sort --numeric-sort --key=2 --reverse | cut --complement --char
- acters=13-40 | numfmt --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest
然后通过 filter-branch
来重写这些大文件涉及到的所有提交(重写历史记录):
git filter-branch -f --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch your-file-name' --tag-name-filter cat -- --all
如果你熟知 Git 的存储方式,跳过此节。
Git 仓库位于项目根目录的 .git
文件夹,其中保存了从仓库建立(git init
)以来所有的代码增删。 每一个提交(Commit)相当于一个 Patch 应用在之前的项目上,借此一个项目可以回到任何一次提交时的文件状态。
于是在 Git 中删除一个文件时,Git 只是记录了该删除操作,该记录作为一个 Patch 存储在 .git
中。 删除前的文件仍然在 Git 仓库中保存着。直接删除文件并提交起不到给 Git 仓库瘦身的效果。
在 Git 仓库彻底删除一个文件只有一种办法:重写(Rewrite)涉及该文件的所有提交。 幸运的是借助 git filter-branch
便可以重写历史提交,当然这也是 Git 中最危险的操作。 可以说比 rm -rf *
危险一万倍。
我清楚地记得曾提交过名为 recent-badge.psd
的文件。这是一个很大的 PhotoShop 文件,我要把它删掉。 filter-branch
命令可以用来重写 Git 仓库中的提交, 利用 filter-branch
的 --index-filter
参数便能把它从所有 Git 提交中删除。
- $ git filter-branch -f --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch assets/img/recent-badge.psd' --tag-name-filter cat -- --all
- Rewrite 2771f50d45a0293668a30af77983d87886441640 (264/982)rm 'assets/img/recent-badge.psd'
- Rewrite 1a98ecb3f39e1f200e31754714eec18bc92848ce (265/982)rm 'assets/img/recent-badge.psd'
- Rewrite d4e61cfb1d88187b0561d283e663b81b738df2c7 (270/982)rm 'assets/img/recent-badge.psd'
- Rewrite 4ba0df06b26cf86fd39c2cda6b012c521cbc4dc1 (271/982)rm 'assets/img/recent-badge.psd'
- Rewrite 242ae98060c77863f5e826ba7e1ec47
--index-filter
参数用来指定一条 Bash 命令,然后 Git 会检出(checkout)所有的提交, 执行该命令,然后重新提交。我们在提交前移除了 recent-badge.psd
文件, 这个文件便从 Git 的所有记录中完全消失了。
--all
参数告诉 Git 我们需要重写所有分支(或引用)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。