과거를 지우고 싶어요 — git history

코드스테이츠에서는 각 서비스 배포를 staging, dev 그리고 master 까지, 3개의 단계를 거치고 있다. 일단 개발자는 최신 upstream dev 를 업데이트시킨 후, local 개발 환경에서 자신이 개발하고자 하는 기능, feature 브랜치를 딴다. 이후, upstream dev 에 PR을 보내고 최종 upstream dev로 모든 기능이 merge 된다.

출처: WormBase Git Workflow

staging은 내가 초기에 단어 이해에 대한 오해가 있어, 지금은 dev로 가기 전 개발자가 마음껏 배포해 볼 수 있는 sandbox 형태로 사용되고 있다. 즉, 위 그림에서 feature -> staging -> master라면 우리는 local -> staging -> dev -> master 이렇게 사용하고 있는 것이다. staging 과 dev를 바꿔쓰고 있었다! 향후 변경해 볼 수 있겠다.

본 글의 요지는 사실 이게 아니고, 아주 오래 오래 전, 우리 서버 개발팀의 리파지토리에 미래를 예상하지 못하고 git history에 포함되어서는 안될 녀석이 포함되어 있는 것을 확인했다. 각 스테이지에 필요한 환경변수중 하나인, pm2에서 일반적으로 권고하는 다이나믹 환경 변수 배포 설정 파일인 ecosystem.config.js 파일이 git history에 포함된 것이다.

알다시피 git 이력에 포함되지 않았으면 하는 파일은 파일 생성 시, .gitignore 파일에 리스트를 적어 놓으면 된다.

하지만 파일 생성 시 기회를 놓치고 git에 이미 포함된 이후에 아무리 .gitignore에 포함시켜봤자 이미 늦은지 오래다. 우리를 힘들게 했던 ecosystem.config.js의 경우 각 스테이지 마다 다른 내용을 담고 있어야 해서 반드시 해결해야 할 파일이었다.

과거 청산이 필요했다. 뿌리를 뽑아내야 했다. 어떻게 하지, 하고 고민하면서 검색을 이렇게 저렇게 해 보다가 좋은 내용을 찾게 되었다.

이 article에서 권고하는 명령어는 바로 아래와 같다.

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch path_to_file" HEAD

이 명령어에서 path_to_file 부분을 내가 지워버리고 싶었던 ecosystem 파일로 지정하면 모든 git history를 돌면서 다 지워버린다. — index-filter 옵션은 트리를 돌지 않고 인덱스를 돌기 때문에 — tre-filter 옵션보다 더 빠르다고 한다. git rm 은 git에서 지운다는 명령어이며 -rf는 recursive 하게 지우는 옵션, 그리고 — cached 는 working directory에서는 그대로 두고 staging index에서만 지운다는 옵션이다. — ignore-unmatch는 언제 이 원치 않는 파일이 add되었는지 몰라도, 즉 이 파일이 존재하지 않는 commit을 돌 때도 error를 내지 않고 그냥 무시한다는 옵션.

그러면 문득 이런 생각이 들 것이다. 혹시라도 리파지토리에 api key 혹은 여러 secret 민감한 정보가 포함된 경우, 이 방법을 통해 지워버리면 되는 것인가?

아니다. 주의해야 한다. 왜냐하면 그 전에 fork & clone 해 간 사람이 있을 수 있고, 그렇지 않더라도 누군가 이미 민감한 비밀 정도를 보고 따로 기록했을 수도 있기 때문이다. 따라서 이런 상황이 발견되었다면 즉시 비밀번호, 혹은 secret 등을 폐기 혹은 변경할 필요가 있다.

--

--