본문 바로가기
IT/형상관리

Git 저장소의 커밋 기록에서 대용량 파일을 삭제하기

by blogger 2022. 5. 10.

Git Repository를 오랜 기간 사용하거나 많은 팀원들이 무수한 커밋 이력을 남기다보면 저장소의 크기(Size)가 점점 커지게 된다. 그런데 커밋에 실수 또는 부주의로 인하여 용량이 큰 파일을 포함하여 저장소에 반영하게 된 경우, 이를 삭제하는 커밋을 생성하여 머지했다 하더라도 여전히 레포지터리 커밋 기록에 존재하게 된다.

 

이러한 레포지터리를 Clone 하게 될 경우, 레포지터리의 크기는 예상보다 큰 공간을 차지하게 되며 네트워크 상황에 따라 소스코드를 다운로드하는 데 많은 시간이 소요되게 된다.

 

 이러한 상태의 레포지터리를 가볍게 만들기 위해 다음의 방법을 사용할 수 있다.

자세한 설명은 github document[https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository] 를 참조하자.

 

 

방법 1. git filter-branch 사용

git filter-branch --tree-filter 'rm -f 대용량파일이름.iso' HEAD

이때 --tree-filter옵션을 사용하면 레포지터리를 체크아웃할 때마다 지정된 명령을 실행한 다음 결과를 다시 커밋한다. 이 경우 존재 여부에 관계없이 모든 스냅샷에서 파일 삭제 명령 (rm -f 대용량파일이름.iso) 가 실행되어 파일을 제거하게 된다.

https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#The-Nuclear-Option:-filter-branch

 

 

방법 2. 대화형 rebase 사용하기

변경을 하고자 하는 커밋의 ID를 확인하여 다음과 같이 커밋 이력을 rebase 한다.

git rebase -i abcdefg #변경하려는커밋아이디  


##### git rebase 를 실행하면 다음과 같이 편집기가 실행되며 도움말이 출력된다.

pick 0101010 Remove Large file
pick 1231231 Add Large file
pick abcdefg initial commit

# Rebase abcdefg..0101010 onto abcdefg
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

수정하려는 커밋 1231231 과 0101010 을 pick -> edit 로 변경 후 편집기를 종료한다.

이후 커밋을 수정하고, git commit --amend 로 커밋 내용을 반영한다.

수정이 완료되면 git rebase --continue 를 실행하여 rebase 를 계속 진행한다.

마지막까지 위 과정을 반복하게 되면 전체 커밋 이력 변경 작업이 완료되고, 커밋 트리를 원격 저장소에 push 해준다.

https://stackoverflow.com/questions/2100907/how-to-remove-delete-a-large-file-from-commit-history-in-the-git-repository

 

방법 3. BFG 툴 사용        ***추천방법

https://rtyley.github.io/bfg-repo-cleaner/

 

BFG Repo-Cleaner by rtyley

$ bfg --strip-blobs-bigger-than 100M --replace-text banned.txt repo.git an alternative to git-filter-branch The BFG is a simpler, faster alternative to git-filter-branch for cleansing bad data out of your Git repository history: Removing Crazy Big Files Re

rtyley.github.io

 

BFG 는 매우 강력한 도구이다.

저장소를 다운받은 후, 해당 저장소의 모든 이력에서 특정 사이즈 이상의 파일을 찾아 모든 이력을 정리할 수 있게 도와준다. 물론 더 많은 옵션을 제공한다.

BFG 툴 사용을 위해서는 위 공식 사이트를 통해 bfg.jar 파일을 다운받고, java 실행환경을 준비한다.

 

10MB이상의 파일을 모든 이력에서 제거하기 위한 사용법 예시는 다음과 같다.

 

우선 레포지터리를 --mirror 옵션과 함께 clone 해 준다.

$ git clone --mirror git://example.com/some-big-repo.git

이후 다음과 같이 10MB 이상의 파일을 모든 이력에서 찾아 삭제해준다.

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

이후 실행 결과 화면을 확인하고, 안내 문구에 따라 나머지 작업을 진행해 주고, git gc 를 실행하여 로컬 저장소의 가비지 컬렉션을 수행한다.

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

 

이후 정리된 저장소를 원격지에 push 하면 모든 작업이 완료된다.