프로젝트를 진행하면서 빠르게 버그를 고치거나 예상치 못한 상황에 대한 작업을 하면서 불필요한 커밋이 생기는 경우가 많습니다. 이럴 경우 커밋으로 기존 작업들을 파악하는 데 어려움이 생기는데요 커밋을 가독성 있게 보고자 Git의 Interactive Rebase 기능과 Squash Merge를 이용해 불필요한 커밋들을 합쳐보겠습니다! 맨 마지막에 요약을 해 놓았으니 빠르게 하셔야 하는 분들은 요약을 보면 좋을거 같습니다 :)
1. 원하는 커밋의 기준점 찾기
git log --oneline
위의 명령어를 입력하여 커밋 히스토리를 확인하고, 합치고자 하는 커밋들이 어느 지점부터 시작되는지 그리고 어디서 끝나는지 확인합니다.
제가 위 명령어를 입력하면 아래와 같이 나옵니다.
전 HOTFIX가 정말 많아서 깃허브에서 각 커밋 히스토리를 보면서 각 HOTFIX를 분류했습니다. 부끄럽네요..ㅠ
2. 합치고 싶은 커밋을 rebase 하기
합치고 싶은 목록의 시작 커밋 이전 커밋을 선택합니다.
git rebase -i <base-commit-hash>
제가 수정하고 싶은 부분은
해당 부분에서 f34a762 - 4830ae0 커밋을 합치고 싶습니다.
그래서 그 이전 커밋인 e0c7bf8를 입력합니다.
git rebase -i e0c7bf8
그럼 위와 같이 뜨는데 합칠 커밋들의 pick을 squash로 바꾸어주고 :wq를 입력해 저장하면 됩니다. 저는 vscode에 새로운 파일 창일 열렸는데 이 경우에는 그 창에서 수정하고 Ctrl + S로 저장한 후 파일을 닫으면 됩니다. 자세한 내용은 아래 설명했습니다.
저같은 경우는 해당 과정에서 3가지 문제를 맞닥뜨렸는데 아래와 같이 해결했습니다.
1. 터미널에 파일이 뜨는 것이 아니라 새로운 파일이 생성됨
제가 vs code에서 git rebase -i e0c7bf8 명령어를 입력했을 때는
위와 같은 파일이 생성되어 당황했었습니다.
이럴 경우 switch to text 버튼을 누르고 pick을 s로 바꿔주면 됩니다.
한 가지 방법이 더 있는데 터미널에서 git config --global --list를 입력해 설정을 확인해주고, 기본적인 설정
core.autocrlf=true
user.name=0000
user.email=0000@gmail.com
init.defaultbranch=main
이렇게가 안되어 있다면,
git config --global --unset core.editor를 입력하여 기본 설정으로 바꾸면 vscode를 이용하지 않고 터미널 내에서 일반적인방법으로 수정이 가능합니다.
2. 합칠려는 커밋 중간에 merge된 브랜치가 있어 관련없는 커밋이 중간에 낌
git log --oneline으로 확인했을 때는 5efec9f 커밋 한 줄만 있어서 몰랐는데
리베이스를 하려고 보니까 5efec9f 커밋이 feat/#1_온보딩프로세스구현 브랜치를 merge한 커밋이기 때문에 해당 브랜치의 커밋들이 중간에 생기는데요
이럴 경우에는 다음과 같이 합치려고 했던 커밋의 시작 커밋 바로 아래에 s를 입력한 커밋들을 입력해야 합니다.
여기서 pick은 '있는 그대로 새 히스토리에 적용하겠다.'라는 의미이고, s(squash)는 '직전(혹은 이전에 pick된) 커밋에 합치되, 메시지도 합쳐서 수정하겠다.'라는 의미입니다.
그렇기에 s가 입력된 커밋을 합치려고 했던
커밋 아래로 배치해야 합니다.
여기서 중요한 점은 사이에 있는 커밋들이 s를 입력한 커밋과 연관되어 있지 않은 경우에만 순서 재배치가 가능합니다. 제가 수정할려고 하는 커밋들은 ci/cd 배포 코드이기에 중간에 있는 커밋들과 연관되어 있지 않습니다. 그래서
이렇게 수정했습니다. 이후 Ctrl + S를 눌러 주고 파일 창을 닫으면 적용됩니다.
3. 수정 중에 실수로 파일창을 닫으며 원치 않는 상태에서 작업이 중단됨
이런 경우에는
git rebase --abort
를 입력하여 리베이스를 취소하면 됩니다.
3. 커밋 이름 새로 짓기
위의 작업을 실행하면 아래와 같은 화면이 뜹니다.
작성된 커밋들을 지우고 원하는 커밋명을 작성해주면 됩니다.
작성 후 2번 작업과 동일하게 :wq를 눌러 저장해 줍니다.
입력할 때는 i를 눌러 입력하고 esc를 눌러 입력을 완료하는 건 모두 아시죠?
4. 충돌 해결
3번 작업이 끝나면 리베이스를 수행하는 과정에서 conflict가 발생하는데 이를 해결하고 git rebase --continue를 해줘야 합니다.
git status 또는 IDE에서 제공하는 기능을 통해 conflict를 해결할 수 있습니다.
충돌을 해결한 후
git add .
git commit --amend
git rebase --continue
명령어를 입력하면 됩니다.
아마 충돌이 계속 발생할 가능성이 큽니다. 그럴 때마다 충돌을 해결하고 위 명령어들을 입력하는 것을 반복해 리베이스가 완료될 때까지 기다립니다.
부가적으로 설명 드리자면 git commit --amend는 이전 커밋에 덮어쓰는 것입니다.
5. git 강제 푸시
리베이스를 모두 완료한 후에
git log --oneline
을 입력해 제대로 적용되었는지 확인하고,
git push --force # 또는 --force-with-lease
를 입력해 강제 푸시를 해주고, main 브랜치와 merge를 해주면 됩니다.
요약
- git log --oneline으로 합치려고 하는 커밋 범위 확인
- git rebase -i {합치려고 하는 커밋들의 시작 커밋의 이전 커밋의 해시값 입력}
- 스쿼시할 커밋을 pick에서 s로 변경 -> :wq를 입력해 저장
- 커밋 이름을 정하는 파일이 뜰 텐데 이전 커밋 이름을 제거하고 원하는 커밋으로 변경 후 :wq
- conflict가 발생할 텐데 충돌해결 -> git add . -> git commit --amend -> git rebase --continue를 반복하여 리베이스를 마무리 해주기
- git log --oneline으로 적용된 것을 확인하고, git push --force로 강제 푸시
오늘도 글 읽어주셔서 감사합니다. 너무 오랜만에 올려서 죄송하기도 하네요ㅠㅠ 앞으로 1주일에 1개씩 업로드 할 예정입니다. 해결하지 못한 문제나 궁금한 것이 있다면 댓글 남겨주세요 제가 해결했던 문제면 포스팅 하겠습니다 :)