git 히스토리에 실수로 추가한 대용량 파일 찾아 제거하기

git 사용 도중 쓸 데 없이 많은 저장공간을 차지하는 경우가 있다. 과거에 필요없는 파일을 추가해버린 경우 이것을 현재 커밋시 제거한다고 해도 과거 커밋해둔 것 때문에 전체 프로젝트 용량은은 거의 그대로 유지됩니다.

따라서 이런 필요없이 많은 용량을 차지하는 파일을 찾아서 삭제해야 되는 경우가 있습니다.

1. git 히스토리에서 대용량 파일 찾기

#!/bin/bash
#set -x 
 
# Shows you the largest objects in your repo's pack file.
# Written for osx.
#
# @see https://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 separator 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's. The pack column is the size of the object, compressed, inside the pack file."
 
output="size,pack,SHA,location"
allObjects=`git rev-list --all --objects`
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=`echo "${allObjects}" | grep $sha`
    #lineBreak=`echo -e "\n"`
    output="${output}\n${size},${compressedSize},${other}"
done
 
echo -e $output | column -t -s ', '

위와 같은 쉘스크립트를 만들어서 find-big-file-from-git.sh 로 저장하고 chmod 700 find-big-file-from-git.sh 로 실행권한을 준다음 프로젝트 폴더에서 실행해 봅니다. (참고로 저자는 MacOS X Catalina 환경입니다. 리눅스와 MacOS 환경등에서는 바로 사용해 볼 수 있습니다.)

% find-big-file-from-git.sh 
All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file.
size   pack  SHA                                       location
16619  1653  3436e147c03362aa71f89780bde4e950b02a6013  folder/big-file.tar.gz
10884  1001  5dd2a2376a40487f752dc36aad4375f4a2c64ac3  big-file2.log

이런식으로 대용량 파일들을 히스토리에서 찾을 수 있네요.

2. git 히스토리에서 대용량 파일 제거하기

원인인 대용량 파일을 찾았다면 이제 삭제해 봐야겠죠?

프로젝트 폴더에서 아래와 같이 삭제할 파일(여기서는 folder/big-file.tar.gz)을 지정해 실행해 봅니다.

% git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch folder/big-file.tar.gz' --prune-empty --tag-name-filter cat -- --all

그러면 아래와 같이 git 히스토리를 모두 뒤져가며 지정한 파일을 삭제해 줍니다.

Rewrite 4aefaa40cf2d1c7185084d2dd2a83d408bd21caf (94/332) (25 seconds passed, remaining 63 predicted)    rm 'folder/bog-file.tar.gz'
Rewrite 34a067056ba80fbc6d5830fc421e5c7eba0fe732 (98/332) (26 seconds passed, remaining 62 predicted)    rm 'folder/bog-file.tar.gz'
Rewrite c1ae2ec9f29bae8c0a7834947362d306759cb5b8 (98/332) (26 seconds passed, remaining 62 predicted)    rm 'folder/bog-file.tar.gz'
Rewrite 8aceb4b972d2693623a4907d0a2e12fcc97dd189 (98/332) (26 seconds passed, remaining 62 predicted)    rm 'folder/bog-file.tar.gz'
Rewrite 0c3ee4cc1522a50502873d3f6af75ee224c14093 (330/332) (86 seconds passed, remaining 0 predicted)     
Ref 'refs/heads/master' was rewritten
Ref 'refs/remotes/origin/master' was rewritten
WARNING: Ref 'refs/remotes/origin/master' is unchanged

모두 삭제하고 나면 원격 저장소에도 강제로 반영해야 합니다.

% git push origin --force --all

이제 새롭게 다시 git clone 으로 내려보면 프로젝트 전체 용량이 많이 줄어든 것을 확인할 수 있습니다. ^^

참고자료 >

  1. https://stackoverflow.com/questions/10622179/how-to-find-identify-large-commits-in-git-history
  2. https://www.deployhq.com/git/faqs/removing-large-files-from-git-history