개요

실수로 github 나 gitlab 의 public 저장소에 큰 파일을 커밋했거나 암호나 SSH private key 같이 민감한 정보를 올린 경우 파일을 삭제하거나 commit history 를 정리해야 합니다.

branch 를 재작성하는 git-filter-branch 명령으로 이런 작업을 할 수 있지만 사용이 어렵고 속도가 느린 단점이 있습니다.


BFG 는 git-filter-branch 명령의 대체제로 빠르고 사용하기 쉬운 장점이 있습니다. (반대 급부로 filter-branch 명령만큼 강력하지는 않습니다.)


BFG 는 java 로 작성되어서 JRE 가 필요하며 binary jar 파일은 maven central 에서 다운로드 받으면 됩니다.

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


사용

1. BFG 로 파일을 삭제하거나 커밋 이력을 정리할 저장소를 --mirror 옵션을 붙여서 clone 합니다.

$ git clone --mirror git@github.com:lesstif/my-repos.git
BASH

이 저장소는 bare 저장소로 일반적인 파일들은 보이지 않지만 저장소의 전체 git database 를 포함하고 있습니다.


2. 이제 저장소로 이동하지 말고 상위 폴더에서 BFG 명령어로 커밋 내역을 정리합니다. 예로 다음은 대상 저장소 커밋 이력에서 크기가 100M 이상인 파일을 삭제합니다.

$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-repos.git
BASH


3. 정리가 끝났으면 저장소로 이동합니다.

$ cd my-repos.git
BASH


4. BFG 는 커밋과 브랜치,  태그를 업데이트했지만 실제 파일이 삭제되거나 변경되지는 않았습니다. local 의 원치않는 dirty data 를 삭제하는 명령인 git-gc 를 실행해서 변경 사항을 반영합니다.

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


5. 완료되었으면 push 해서 원격 저장소에 반영합니다.

$ git push
BASH


예제

정리후 위 절차의 3번부터 실행해서 저장소에 반영하고 push 까지 마쳐야 합니다.

큰 파일 삭제

크기가 50M 이상인 모든 파일을 삭제합니다.

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

SSH 개인키 삭제

id_rsa 나 id_dsa 로 시작하는 SSH 개인키 파일들을 모두 삭제합니다.

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


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

설정 파일등에 DB 접속 암호등 민감한 정보를 포함해서 커밋했을 경우  -rt, --replace-text  <expressions-file> 명령을 사용해서 제거할 수 있습니다.

<expressions-file>에는 패턴과 대체할 문자열을 적어 주면 되며 regex: 접두어를 붙이면 정규식 형식도 가능합니다.


실수로 Access Token 과 실제 domain 을 추가해서 커밋했고 내역 삭제를 위해서 expressions-file 파일을 만들었습니다.

regex:jira.server.url=.*==>ijra.server.url=https://your-jira.host.here
regex:jira.user.pat=.*==>ijra.user.url=your-personal-token-here
CODE


이제 다음 명령으로 민감 정보를 포함한 커밋을 정리합니다.

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

Using repo : C:\Users\lesstif\github\java\jira-rest-client

Found 44 objects to protect
Found 10 commit-pointing refs : HEAD, refs/heads/develop, refs/heads/main, ...
Found 3 tag-pointing refs : refs/tags/RELEASE-0.6.1, refs/tags/v0.0.2, refs/tags/v0.7.1

Protected commits
-----------------

These are your protected commits, and so their contents will NOT be altered:

 * commit 903fa3a9 (protected by 'HEAD') - contains 2 dirty files :
        - README.md (5.5 KB)
        - jira-rest-client.properties.example (285 B )
...
Changed files
-------------

        Filename                              Before & After
        ---------------------------------------------------------------------------------------------------
        jira-rest-client.properties.example | a32ac01d ⇒ 405ef3b3, 2a9ce72c ⇒ d8f8bac1, 026ffea8 ⇒ 859e789d


In total, 11 object ids were changed. Full details are logged here:

BASH



Ref