Git Rebase: 커밋 히스토리 깔끔하게 관리하는 방법
Git rebase의 개념과 사용법을 익혀 커밋 히스토리를 효율적으로 관리하고 브랜치 통합을 깔끔하게 만드는 방법을 배웁니다.
Git Rebase: 커밋 히스토리 깔끔하게 관리하기
Git의 rebase 명령어는 현재 브랜치의 기반(base)을 다른 브랜치로 변경하는 강력한 도구입니다. 이를 통해 커밋 히스토리를 보다 깔끔하고 선형적으로 만들어 코드 리뷰 및 협업 효율성을 높일 수 있습니다. 이 가이드에서는 git rebase의 개념, 언제 사용해야 하는지, 그리고 실제 사용법과 주의사항을 설명합니다.
1. Git Rebase란 무엇인가?
git rebase는 특정 브랜치의 커밋들을 다른 브랜치 위로 '재배치(re-apply)'하는 명령어입니다. 즉, 현재 브랜치의 시작점을 다른 브랜치의 최신 커밋으로 옮기는 과정입니다. 이는 마치 시간 여행을 해서 현재 브랜치의 작업이 나중에 커밋된 것처럼 보이게 만드는 것과 같습니다.
1.1. Rebase의 핵심 아이디어
- 커밋 히스토리 재작성:
rebase는 기존 커밋을 그대로 사용하는 것이 아니라, 현재 브랜치의 변경 사항들을 새로운 기반 브랜치 위에서 '새로운 커밋'으로 다시 만듭니다. - 선형적인 히스토리:
rebase를 사용하면 커밋들이 시간 순서대로 일렬로 나열된 것처럼 보이는 깔끔한 히스토리를 만들 수 있습니다. 이는git merge로 인해 발생하는 불필요한 병합 커밋을 줄여줍니다.
2. 언제 Git Rebase를 사용해야 하는가?
rebase는 주로 다음과 같은 상황에서 유용합니다:
2.1. 개발 중인 로컬 브랜치 최신 상태 유지
main 또는 develop과 같은 메인 브랜치에서 파생된 자신의 기능 개발 브랜치가 있을 때, 메인 브랜치가 업데이트되면 rebase를 사용하여 자신의 브랜치를 최신 상태로 유지할 수 있습니다. 이를 통해 나중에 메인 브랜치로 병합(merge)할 때 발생할 수 있는 충돌을 미리 해결하고, 깔끔한 히스토리를 유지할 수 있습니다.
2.2. 공유되지 않은 브랜치의 히스토리 정리
아직 원격 저장소에 푸시(push)하지 않은 로컬 브랜치의 커밋 히스토리를 정리하고 싶을 때 rebase를 사용할 수 있습니다. 예를 들어, 여러 개의 작은 커밋을 하나의 의미 있는 커밋으로 합치거나, 커밋 메시지를 수정하고 싶을 때 유용합니다.
3. Git Rebase 사용법
rebase는 크게 두 가지 방식으로 사용됩니다. 하나는 다른 브랜치를 현재 브랜치에 적용하는 것이고, 다른 하나는 현재 브랜치의 커밋들을 상호 작용하며 수정하는 것입니다.
3.1. 브랜치를 다른 브랜치 위로 재배치하기
가장 일반적인 사용법은 현재 작업 중인 브랜치를 다른 브랜치(예: main)의 최신 커밋 위로 옮기는 것입니다.
- 대상 브랜치로 이동: 먼저, 재배치될 브랜치(예:
main)로 이동하여 최신 상태로 업데이트합니다.git checkout main git pull origin main - 기능 브랜치로 이동: 다시 자신의 기능 개발 브랜치로 돌아옵니다.
git checkout feature-branch - Rebase 수행: 기능 브랜치의 기반을
main브랜치의 최신 커밋으로 재설정합니다.
이 과정에서git rebase mainmain브랜치의 새로운 커밋들이 기능 브랜치 위에 순차적으로 적용됩니다. 만약 변경 사항 간에 충돌이 발생하면, Git이 멈추고 충돌 해결을 요청합니다. - 충돌 해결 (필요시):
- 충돌이 발생하면, 해당 파일을 수정한 후
git add <충돌_파일>명령어로 스테이징합니다. - 모든 충돌을 해결했다면
git rebase --continue명령어로 재배치를 계속 진행합니다. - 재배치를 중단하고 싶다면
git rebase --abort명령어를 사용합니다.
- 충돌이 발생하면, 해당 파일을 수정한 후
- 원격 저장소 푸시:
rebase는 히스토리를 재작성하므로, 이미 원격에 푸시된 커밋에 대해rebase를 수행했다면git push --force-with-lease또는git push -f명령어를 사용하여 강제로 푸시해야 합니다. 주의: 이미 공유된 브랜치에rebase를 강제 푸시하는 것은 다른 협업자에게 문제를 일으킬 수 있으므로 신중해야 합니다.
3.2. 대화형 Rebase (Interactive Rebase)
git rebase -i 명령어는 커밋 히스토리를 더욱 세밀하게 제어할 수 있게 해줍니다. 이를 통해 커밋을 합치거나(squash), 순서를 바꾸거나, 커밋 메시지를 수정하거나, 심지어 커밋을 삭제할 수도 있습니다.
-
대화형 Rebase 시작: 현재 브랜치에서 최근 N개의 커밋에 대해 대화형
rebase를 시작합니다.# 최근 3개의 커밋에 대해 대화형 rebase 시작 git rebase -i HEAD~3또는 특정 커밋(예:
abc1234) 이전 커밋들부터 대화형 rebase를 시작할 수도 있습니다.git rebase -i abc1234 -
명령어 편집: Git은 텍스트 편집기를 열어 수정할 커밋 목록을 보여줍니다. 각 커밋 라인에는
pick이라는 명령어가 앞에 붙어 있습니다. 이pick대신 다른 명령어를 사용하여 커밋을 조작할 수 있습니다.pick a1b2c3d Commit message 1 pick e4f5g6h Commit message 2 pick i7j8k9l Commit message 3주요 명령어:
pick(p): 커밋을 그대로 사용합니다.reword(r): 커밋은 사용하되, 커밋 메시지를 수정합니다.edit(e): 커밋을 사용하되, 커밋 시점에서 멈춰 수정을 가합니다 (예: 커밋 분리).squash(s): 커밋을 이전 커밋과 합칩니다. 합쳐질 때 커밋 메시지를 수정할 수 있습니다.fixup(f):squash와 유사하지만, 합쳐질 때 커밋 메시지는 버리고 이전 커밋 메시지를 그대로 사용합니다.drop(d): 커밋을 삭제합니다.reorder: 커밋 라인의 순서를 변경하여 커밋 적용 순서를 바꿉니다.
-
수정 후 저장: 편집기에서 원하는 대로 명령어를 수정하고 저장한 후 닫습니다.
reword나squash를 사용한 경우, Git이 추가 편집기를 열어 커밋 메시지를 수정하도록 안내합니다.edit을 사용한 경우, 해당 커밋 시점에서 Git이 멈춥니다. 여기서 변경사항을 추가하거나 커밋을 분리한 후git rebase --continue를 실행합니다.
-
히스토리 확인:
git log --oneline --graph등으로 변경된 히스토리를 확인합니다. -
강제 푸시: 대화형
rebase로 히스토리를 재작성한 경우, 원격 저장소에 강제 푸시가 필요할 수 있습니다 (git push -f).
4. Rebase 사용 시 주의사항
rebase는 강력하지만, 잘못 사용하면 데이터를 잃거나 협업에 문제를 일으킬 수 있습니다.
- 공유된 브랜치에서의 사용 금지: 이미 원격 저장소에 푸시되어 다른 팀원들이 사용하고 있는 브랜치에
rebase를 사용하는 것은 매우 위험합니다.rebase는 커밋 히스토리를 재작성하므로, 다른 팀원들의 로컬 저장소와 원격 저장소의 히스토리가 달라져 심각한 혼란을 야기할 수 있습니다. 공유된 브랜치에는git merge를 사용하는 것이 일반적입니다. - 신중한 강제 푸시:
rebase후 원격에 푸시할 때는git push -f또는git push --force-with-lease와 같이 히스토리를 강제로