..

【翻译】给git仓库瘦身

某些特殊的原因,我们不小心把一个较大的文件加入到了 git 仓库,并且我们提交了它,git 仓库的大小会瞬间的膨胀起来,有些时候,我们甚至都不知道我们加入的是那个大文件导致,即使我们找到了这个文件,将他从 git 仓库中删除了,但是仓库并没有完全的变小,因为在 .git 这个文件中还保存着这个大文件的内容。我们处理这个问题分三个步骤:

  • 找到这个大文件
  • 将大文件从仓库中删除
  • 修改 .git 服务器中的文件

clone仓库

如果你本地还没有仓库,那么你应该先将仓库下载到本地

git clone remote-url

现在你本地有这了这个仓库了,但是你还没有全部的分支,为了保证大文件能能够完全的干净的删除,你需要获取所有的分支,完成这个工作,你还需要一个脚本:

for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do
    git branch --track ${branch##*/} $branch
done

找到大文件

这里有一个脚本,帮助我们找到那个大文件

#!/bin/bash
#set -x 

# Shows you the largest objects in your repo's pack file.
# Written for osx.
#
# @see http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
# @author Antony Stubbs

# set the internal field spereator to line break, so that we can iterate easily over the verify-pack output
IFS=$'\n';

# list all objects including their size, sort by size, take top 10
objects=`git verify-pack -v .git/objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head`

echo "All sizes are in kB. The pack column is the size of the object, compressed, inside the pack file."

output="size,pack,SHA,location"
for y in $objects
do
	# extract the size in bytes
	size=$((`echo $y | cut -f 5 -d ' '`/1024))
	# extract the compressed size in bytes
	compressedSize=$((`echo $y | cut -f 6 -d ' '`/1024))
	# extract the SHA
	sha=`echo $y | cut -f 1 -d ' '`
	# find the objects location in the repository tree
	other=`git rev-list --all --objects | grep $sha`
	#lineBreak=`echo -e "\n"`
	output="${output}\n${size},${compressedSize},${other}"
done

echo -e $output | column -t -s ', '

执行这个脚本,你将看到如下的内容:

All sizes are in kB. The pack column is the size of the object, compressed, inside the pack file.
size     pack    SHA                                       location
1111686  132987  a561d25105c79aa4921fb742745de0e791483afa  08-05-2012.sql
5002     392     e501b79448b9e970ab89b048b3218c2853fdfc88  foo.sql
266      249     73fa731bb90b04dcf79eeea8fdd637ba7df4c089  app/assets/images/fw/iphone.fw.png
265      43      939b31c563bd40b1ca70e4f4a9f7d67c27c936c0  doc/models_complete.svg
247      39      03514d9e84418573f26b205bae7e4e57057c036f  unprocessed_email_replies.sql
193      49      6e601c4067aaddb26991c4bd5fbddef003800e70  public/assets/jquery-ui.min-0424e108178defa1cc794ee24fc92d24.js
178      30      c014b20b6fed9f17a0b2809ac410d74f291da26e  foo.sql
158      158     15f9e56bc0865f4f303deff053e21909661a716b  app/assets/images/iphone.png
103      36      3135e15c5cec75a4c85a0636b154b83221020c97  public/assets/application-c65733a4a64a1a885b1c32694574b12a.js
99       85      c1c80bc4c09e692d5e2127e39c87ecacdb1e816f  app/assets/images/fw/lovethis_logo_sprint.fw.png

现在,你已经看到了,最大的那个文件是一个1.1GB的SQL dump文件。

清除大文件

清理大文件会花掉相当长的一段时间,这取决你仓库的使用频率,你只需要执行如下命令即可:

 git filter-branch --tag-name-filter cat --index-filter 'git rm -r --cached --ignore-unmatch filename' --prune-empty -f -- --all

这里的 filename 填写你需要删除的文件的名字或者是通配符。然后继续执行如下的命令:

rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

至此,你可以使用 du -sh 命令查看,仓库大小已经变小了很多。

发布本地仓库

现在只是本地仓库变小了,我们需要将我们的更改发布到远程仓库.

git push origin --force --all
git push origin --force --tags

现在再次 clone 仓库,发现仓库变小了很多。

原文出处