github를 통해 작업을 진행하다 보면 commit에 원치 않는 파일이나 메시지가 들어가는 경우가 있다.
이를 바로 발견하여 수정하면 쉽게 해결할 수 있지만 모르고 작업하다가 나중이 되어서야 알게 됐거나 너무 많은 commit에 올라갔다면 상황이 복잡해진다.
예를 들어 AWS SecretKey가 commit에 유출되었는데 너무 많은 커밋에 유출되어 하나하나 수정하기 힘든 경우가 이에 해당된다.
다행히 이러한 경우 일괄적으로 commit을 수정하는 방법이 있다.
- git filter-branch
- git filter-repo
위 두 가지 기능으로 Git 리포지토리의 commit history를 재작성할 수 있다.
두 기능에는 일괄적으로 commit 메시지를 수정하거나 특정 파일을 commit history에서 수정하거나 제거하는 기능이 있는데 이번 글에서는 특정 파일을 커밋 히스토리에서 제거하는 방법에 대해 설명해보겠다.
git filter-branch
삭제하고 싶은_파일_경로
위치에 삭제를 원하는 파일 경로를 넣고 아래 명령어를 입력한다.
아래 명령어를 실행하면 파일이 삭제된 뒤 남는 빈 커밋들이 남게 된다.
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch 삭제하고_싶은_파일_경로' --tag-name-filter cat -- --all
만약 빈 커밋들을 모두 삭제하고 싶다면 아래 명령어처럼 --prune-empty
를 추가하여 빈 커밋들을 삭제할 수 있다.
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch 삭제하고싶은_파일_경로' --prune-empty --tag-name-filter cat -- --all
예를 들어, build/libs/spring.jar 파일을 과거 커밋 이력에서 지우고 싶다면 아래와 같이 입력하면 된다.
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch build/libs/spring.jar' --tag-name-filter cat -- --all
명령어를 입력하면 아래 사진과 같이 실행되고 있다는 메시지가 나온다.
실행이 완료되면 아래 사진처럼 commit history가 rewritten 됐다는 메시지가 나오고 끝난다.
이 방법은 속도가 너무 느리다는 단점이 있다. 만약 500개의 커밋을 수정해야 한다면 정말 ......... 오래 걸린다 ...(경험담임 😢 )
따라서 이 방법보다 더 빠른 방법을 소개하겠다.
git filter-repo
git filter-repo
는 git filter-branch
의 대안으로, 리포지토리의 히스토리를 보다 효율적으로 수정할 수 있다. 즉, 훨씬 더 빠르고 안전하게 동작한다.
다만 빈 커밋을 유지할 수 있는 방법은 없기 때문에 빈 커밋을 유지하고 싶다면 git filter-branch
를 사용해야 한다. 오래 걸려도.. 어쩔 수 없다 😢
삭제하고 싶은_파일_경로
위치에 삭제를 원하는 파일 경로를 넣고 아래 명령어를 입력한다.
git filter-repo --invert-paths --path 삭제하고_싶은_파일_경로 --keep-empty
예를 들어, build/libs/spring.jar 파일을 과거 커밋 이력에서 지우고 싶다면 아래와 같이 입력하면 된다.
git filter-repo --invert-paths --path build/libs/spring.jar --keep-empty
명령어를 입력하면 아래 사진과 같이 뜬다.