깃헙 history를 주물러봅시다

서론

때는 2021년 5월13일. Ecommerce-react-django 프로젝트를 완성후 배포테스트를 위해 작업중 각종 비밀번호를 하드코딩해서 넣었었는데 commit 할때에 환경변수로 바꿨다고 생각하였으나 저장되지않아 aws rds db비밀번호, aws_access_key_id와 aws_secret_access_key를 있는 그대로 커밋후 리모트에 푸시해버렸습니다.

얼마 지나지 않아서 Gitguardian 한테 중요한 정보가 노출되었다고 메일이 왔습니다 Gitguardian은 git에서 운영하는건줄 알았는데 아니었습니다. 이 친구들은 github유저의 모든 푸시데이터를 감시하는건지 어쩐지 모르겠지만 Gitguardian에 sign한적도 없는데 실수로 민감한 정보를 올릴때마다 Alert 메일을 보내옵니다.


과거에 저는 새로운 커밋으로 덮으면 과거 기록은 못 보는줄 알고 얼른 비밀번호를 환경변수로 바꾼후 다시 푸시 했었습니다. 하지만 commits history를 보면 비밀번호에 관한정보는 그대로 담겨있었고 history 수정 방법을 몰라 쌓아왔던 잔디를 포기하며 새로운 repo를 파서 다시 푸시했었습니다. 잔디들을 잃는 고통은 뼈를깎는 고통과 같았지만 어쩔 수 없었습니다.


하지만 이번에는 얘기가 달랐습니다.
이 2주동안 진행한 개인 프로젝트였는데 14일치의 잔디(총 50+ commits) 들을 통으로 없애기는 정말 싫었고, history를 수정할 방법을 찾고 말겠다고 다짐후 결국 찾았습니다.

이 글을 본 여러분들은 잔디를 잃지않고도 누출된 비밀정보의 history를 마음대로 주무를 수 있을 것입니다.

1. BGF Repo-Cleaner 설치

아래의 링크로 이동하여 해당 파일을 다운로드받으세요 만약 자바가 설치되어있지않다면 자바 또한 설치해주세요.

BGF Repo-Cleaner 다운로드하기

Download 폴더안에 파일이 있을겁니다

#.zshrc
alias bfg='java -jar ~/Downloads/bfg-1.14.0.jar'

추후에도 편하게 쓰기위해 alias를 설정해줍니다.

2. 히스토리를 변경하고자하는 폴더로 들어갑니다.

git init을 했던 위치로 이동하면되는 겁니다.

터미널에 ls -a 했을때 .git 이 보이면 모든 준비가 끝이났습니다.

3. 여러가지 옵션.

option 1.

만약 HelloWorld.txt에 관한 모든 커밋 히스토리를 없애고싶다면 터미널에

$ bfg --delete-files HelloWorld.txt .git 

뭔가 여러줄뜰거에요. 끝나고나면

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

입력해서 원하지않는 모든 dirty data를 삭제할거에요 그 다음,

$ git push -f <remote-repo> <localbranchname>

입력하여 리모트 리포로 하드 푸시해줍니다.

최신의(오류를 모드 제거했다고 가정함으로)커밋을 제외한 모든 히스토리에서 해당파일정보는 보이지 않을거에요.

option 2.

파일에관한 히스토리는 모두유지하면서 원하는 정보만 가리고싶을때에는 이 방법을 이용하세요.


#settings.py

AWS_ACCESS_KEY_ID = 'itsmyaccesskeyid'
AWS_SECRET_ACCESS_KEY = 'itsmysecretaccesskey'

이방법을 쓰면 모든 히스토리에 있는 모든 ‘itsmyaccesskeyid’ 나 ‘itsmysecretaccesskey’ 를 아래와 같이 ***REMOVED*** 로 바꾸거나 원하는대로 바꿔줄 수 도있습니다.

AWS_ACCESS_KEY_ID = ***REMOVED***
AWS_SECRET_ACCESS_KEY = ***REMOVED***

먼저 replacements.txt를 만들어봅시다 (.git 이 위치한 폴더에) 여기에도 여러가지 옵션이있고, 정규표현식도 이용할 수 도 있지만 간단한 옵션들만 설명하겠습니다.

#replacements.txt
itsmyaccesskeyid                           # itsmyaccesskeyid 를 '***REMOVED***' 로 바꿔줍니다 (default)
itsmysecretaccesskey==>examplePass         # itsmysecretaccesskey 를 'examplePass' 로 바꿔줍니다.
PASSWORD3==>                               # PASSWORD 를 '' 로 바꿔줍니다.

귀찮다 싶으시면 그냥 txt파일 하나만들고, 민감한정보 모두를 나열해주시면됩니다. (변수명이 아닌 정보 그자체를 나열해야합니다)

자 이제 모든 정보를 지울 준비가 완료되었습니다.

터미널에

$ bfg --replace-text replacements.txt .git

입력후 엔터쳐주세요

그다음 option1 과 마찬가지로

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

입력해서 원하지않는 모든 dirty data를 삭제후

$ git push -f <remote-repo> <localbranchname>

입력하여 리모트 리포로 하드 푸시해줍니다.