Git에 큰 파일 및 인증키을 올렸을 경우 이력 삭제하기 - bfg-repo-cleaner

실수로 git의 public 저장소에 용량 큰 파일을 commit을 하였을 거나, 인증키, 비밀번호와 같이 민감한 정보를 올린 경우가 있다. 그럴 경우에 파일을 삭제하거나 commit history에 기록을 삭제 하고 싶은 경우 있을 것이다. 이럴 때 사용하는 bfg-repo-cleaner를 소개하려고 한다.

설치

BFG는 Java로 개발되어 JRE Java 8 이상이 필요하며, jar 파일형태로 되어 있는다.

jar 바이너리는 maven central에 저장되어 아래 명령로 받거나, 브라우저에 집접 연결해서 받을 수 있다.

$ curl -o bfg.jar -L https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar

사용법

저장소 clone 받기

먼저 다음 --mirror 플래그를 사용하여 저장소의 새 사본을 복제(clone) 받는다.

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

이렇게 클론을 받으면 이 저장소는 베어(bare) 저장소가 되므로 일반 파일은 표시되지 않지만, 저장소의 Git 데이터베이스 전체 사본이 된다. 이때 혹시 모를 일 대비해서 이 시점에 백업을 해야 한다.

저장소 정리

이제 BFG를 실행하여 저장소를 정리할 수 있다.

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

여기 예에서는 용량이 큰 파일을 제거하는 방법이 예시로 되어 있고, 아래 사용 예제를 보고 민감한 파일 삭제 및 민감한 정보 커밋 이력 변경 등을 하면 된다.

변경된 사항 저장소 반영

BFG는 커밋과 모든 브랜치 및 태그를 업데이트하여 정리하지만 원하지 않는 항목을 물리적으로 삭제하지는 않는다. 저장소를 검사하여 기록이 업데이트되었는지 확인한 다음에, 표준 git gc 명령을 사용하여 원하지 않는 dirty data를 제거한다.

$ cd some-big-repo.git
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive

원격 저장소 반영

마지막으로 저장소의 업데이트된 상태에 만족하면 다시 푸시한다(복제 명령에서 플래그를 사용했기 때문에 이 푸시는 원격 서버의 모든 --mirror 참조를 업데이트한다) .

$ git push

모두 새로운 복제본으로 교체

이것으로 모든 사람의 저장소의 이전 복사본을 지우고 새로운 복제본을 교체하면 된다.
새로 정리된 저장소에 기존에 dirty history를 다시 넣게 될 수 있는 위험이 있으므로, 이전 클론은 모두 삭제하는 것이 가장 좋다.

사용 예제

민감한 파일 삭제

파일 이름이 ‘id_rsa’ 또는 ‘id_dsa’인 SSH 개인키 파일들 모두 삭제한다.

$ java -jar bfg.jar --delete-files id_{dsa,rsa}  my-repo.git

용량 큰 파일 삭제

50MB보다 큰 모든 Blob(Binary Large Object)을 제거한다.

$ java -jar bfg.jar --strip-blobs-bigger-than 50M  my-repo.git

민감한 정보 포함한 커밋 이력 변경

인증키, 비밀번호 등 민감한 정보를 포함해서 커밋을 하였을 경우에는 bfg 명령에 -rf, --replace-text {filename} 옵션으로 제거할 수 있다.

$ java -jar bfg.jar --replace-text passwords.txt  my-repo.git

여기서 파일에 나열된 모든 암호문에 regex:를 접두어로 붙이면 정규식으로 가능하고, 디폴트로는 암호문을 ***REMOVED***으로 치환한다.

passwords.txt 예시는 아래와 같다.

PASSWORD1                       # Replace literal string 'PASSWORD1' with '***REMOVED***' (default)
PASSWORD2==>examplePass         # replace with 'examplePass' instead
PASSWORD3==>                    # replace with the empty string
regex:password=\w+==>password=  # Replace, using a regex
regex:\r(\n)==>$1               # Replace Windows newlines with Unix newlines

참조




최종 수정 : 2023-05-08