2-5. Git의 rebase: 브랜치 재배치

1. Git rebase란 무엇인가?

Git의 rebase는 브랜치를 다른 브랜치 위에 "재배치"하는 강력한 기능입니다. 이는 브랜치들의 커밋 히스토리를 변경하여, 마치 다른 브랜치에서 파생된 것처럼 보이게 만드는 효과를 줍니다. rebase는 merge와 유사한 결과를 낼 수 있지만, 히스토리를 재작성한다는 점에서 큰 차이를 보입니다.

1) rebase의 개념

rebase는 브랜치를 다른 브랜치에 통합하는 또 다른 방법입니다. 기본적으로 다음 단계를 거칩니다.

  1. 브랜치 분리 지점 찾기: rebase하려는 브랜치와 대상 브랜치의 공통 조상을 찾습니다.
  2. 변경 사항 임시 저장: rebase하려는 브랜치에서 공통 조상 이후의 모든 커밋을 임시로 저장합니다.
  3. 대상 브랜치에 적용: 대상 브랜치를 최신 상태로 업데이트한 후, 임시로 저장했던 커밋들을 대상 브랜치의 가장 최신 커밋 위에 순서대로 적용합니다.
  4. 히스토리 재작성: 결과적으로 rebase를 수행한 브랜치는 대상 브랜치를 기준으로 재구성된 새로운 커밋 히스토리를 갖게 됩니다.

이 과정에서 커밋 메시지나 변경 사항은 유지되지만, 커밋 해시는 변경됩니다. 이는 rebase가 커밋을 "새롭게 만드는" 작업이기 때문입니다.

2) merge와의 비교

mergerebase 모두 브랜치를 통합하는 데 사용되지만, 히스토리 관리 방식에서 차이가 있습니다.

  • merge: 브랜치를 병합할 때, 별도의 병합 커밋(merge commit)을 생성하여 두 브랜치의 히스토리를 묶습니다. 이는 각 브랜치의 히스토리를 보존하지만, 복잡한 히스토리 그래프를 만들 수 있습니다.

    merge 개념 설명 뒤

  • rebase: 브랜치를 재배치할 때, 히스토리를 선형적으로 유지합니다. 즉, rebase 후에는 마치 한 브랜치에서 쭉 작업한 것처럼 보입니다.

    rebase 개념 설명 뒤

기능 merge rebase
히스토리 병합 커밋 생성, 히스토리 보존 히스토리 재작성, 선형적 히스토리
복잡성 히스토리 그래프 복잡해질 수 있음 히스토리 단순
충돌 해결 병합 충돌 발생 가능, 수동 해결 필요 rebase 과정에서 충돌 발생 가능, 수동 해결 필요 (commit 순서대로 충돌 해결)
사용 목적 브랜치 통합, 히스토리 보존 브랜치 통합, 히스토리 정리, 깔끔한 히스토리 유지, 변경 사항의 순차적 적용
원격 저장소 원격 저장소에 바로 푸시 가능, merge 커밋이 남음 원격 저장소에 푸시 전에 rebase 수행 시 강제 푸시(--force-with-lease) 필요, 히스토리 수정

2. rebase의 작동 원리

rebase는 다음과 같은 세부 단계를 거쳐 작동합니다.

  1. rebase 시작: rebase 명령을 실행하면 Git은 먼저 rebase를 수행할 브랜치(feature branch)의 마지막 커밋과 대상 브랜치(main branch)의 공통 조상을 찾습니다.
  2. 패치 생성: feature branch의 공통 조상 이후의 각 커밋에 대한 변경 사항(diff)을 patch 형식으로 생성하여 임시로 저장합니다.
  3. 대상 브랜치로 이동: feature branch를 대상 브랜치(main branch)의 최신 커밋으로 이동시킵니다.
  4. 패치 적용: 저장된 각 패치를 대상 브랜치에 차례대로 적용합니다. 이 과정에서 각 패치에 해당하는 변경 사항을 새로운 커밋으로 생성합니다.
  5. 충돌 해결: 패치를 적용하는 과정에서 충돌이 발생할 수 있습니다. 충돌이 발생하면 수동으로 해결한 후, git add 명령으로 해결된 파일을 스테이징 영역에 추가하고 git rebase --continue 명령을 실행하여 다음 패치를 적용합니다. 모든 패치가 성공적으로 적용되면 rebase가 완료됩니다.

1) 상세 과정 예시

다음과 같은 상황을 가정해 봅시다.

  1. main 브랜치에서 A, B, C 커밋이 있습니다.
  2. feature 브랜치를 main 브랜치에서 생성한 후, DE 커밋이 추가되었습니다.
  3. main 브랜치에 F 커밋이 추가되었습니다.

이 상황에서 feature 브랜치를 main 브랜치에 rebase하면 다음과 같은 과정이 진행됩니다.

  1. Git은 mainfeature 브랜치의 공통 조상인 A 커밋을 찾습니다.
  2. DE 커밋의 변경 사항을 패치로 저장합니다.
  3. feature 브랜치를 main 브랜치의 최신 커밋(F)으로 이동합니다.
  4. D의 변경 사항을 적용하여 새로운 커밋 D'를 생성합니다.
  5. E의 변경 사항을 적용하여 새로운 커밋 E'를 생성합니다.
  6. 결과적으로 feature 브랜치는 main 브랜치 위에 D'E' 커밋을 갖게 됩니다. 이제 feature 브랜치는 F, D', E' 커밋을 갖게 됩니다.

3. rebase 사용법

rebase 명령어는 간단하지만, 그 효과는 매우 강력합니다.

1) 기본 사용법

rebase는 일반적으로 다음과 같은 방식으로 사용합니다.

git checkout <feature-branch>  # rebase할 브랜치로 이동
git rebase <target-branch>    # 대상 브랜치에 rebase 수행

예를 들어, feature 브랜치를 main 브랜치에 rebase하려면 다음과 같이 실행합니다.

git checkout feature
git rebase main

2) 충돌 해결

rebase 과정에서 충돌이 발생하면, Git은 rebase를 일시 중지하고 충돌을 해결하도록 안내합니다.

  1. 충돌 확인 및 해결: 충돌이 발생한 파일을 열어 수정하고, 원하는 대로 변경 사항을 병합합니다.
  2. git add: 수정된 파일을 스테이징 영역에 추가합니다.
  3. git rebase --continue: 다음 커밋의 rebase를 계속 진행합니다.
  4. git rebase --abort: rebase를 중단하고 원래 상태로 되돌립니다.

충돌을 해결하는 과정은 merge와 유사하지만, rebase는 각 커밋에 대해 개별적으로 충돌을 해결해야 한다는 점이 다릅니다.

4. rebase의 장점과 단점

rebase는 강력한 기능이지만, 모든 상황에 적합한 것은 아닙니다. 장점과 단점을 정확히 이해하고 사용해야 합니다.

1) 장점

  • 깔끔한 히스토리: rebase는 히스토리를 선형적으로 유지하여, 코드의 흐름을 이해하기 쉽게 만듭니다. 불필요한 merge 커밋이 없어 히스토리가 깔끔해집니다.
  • 쉬운 되돌리기: rebase 후, 변경 사항을 되돌리려면 단순히 git reset --hard 명령을 사용하여 원래 브랜치로 되돌릴 수 있습니다.
  • 코드 리뷰 용이: rebase를 사용하면 코드 리뷰 시 변경 사항을 순차적으로 확인하기 쉽습니다.

2) 단점

  • 히스토리 변경: rebase는 히스토리를 변경하므로, 이미 공유된 커밋에 대해 rebase를 수행하면 문제가 발생할 수 있습니다.
  • 충돌 발생 가능성: rebase 과정에서 충돌이 발생할 수 있으며, 충돌 해결 과정이 복잡할 수 있습니다.
  • 원격 브랜치: 공유된 원격 브랜치에 rebase를 수행한 후 push할 때는 --force-with-lease 옵션을 사용해야 하므로 주의해야 합니다.

5. rebase 사용 시 주의사항

rebase는 매우 유용한 기능이지만, 사용 시 몇 가지 주의해야 할 사항이 있습니다.

1) 공개된 커밋에 rebase 금지

이미 원격 저장소에 push된 커밋에 대해 rebase를 수행하는 것은 피해야 합니다. 이렇게 하면 다른 개발자들이 해당 커밋을 기반으로 작업한 경우, 히스토리 충돌이 발생하고, 작업 손실의 위험이 있습니다. 원칙적으로 다른 사람과 공유하는 브랜치에서는 rebase를 사용하지 않는 것이 좋습니다.

2) 개인 브랜치에서 사용

rebase는 개인적으로 작업하는 브랜치, 즉, 아직 다른 사람과 공유하지 않은 브랜치에서 사용하는 것이 좋습니다. 이 경우, 히스토리를 자유롭게 수정하고, 깔끔한 히스토리를 유지할 수 있습니다.

3) rebasepush

rebase 후 원격 저장소에 변경 사항을 push할 때는 주의해야 합니다. 히스토리가 변경되었기 때문에, 일반적인 git push 명령으로는 거부될 수 있습니다. 이 경우, --force-with-lease 옵션을 사용하여 강제로 push해야 합니다. 하지만, 이 옵션은 다른 사람의 작업에 영향을 줄 수 있으므로, 신중하게 사용해야 합니다.

git push --force-with-lease origin <feature-branch>

4) 대규모 rebase 피하기

대규모 rebase는 충돌 해결 과정이 매우 복잡해질 수 있습니다. rebase 전에, 변경 사항을 작은 단위로 나누어 commit하고, 정기적으로 rebase를 수행하여, 충돌 발생 가능성을 줄이는 것이 좋습니다.

6. rebase 활용 시나리오

rebase는 다양한 상황에서 유용하게 활용될 수 있습니다.

1) feature branch 정리

개인 브랜치에서 작업하는 동안, main 브랜치에 최신 변경 사항을 적용하고 싶을 때 rebase를 사용합니다.

git checkout feature-branch
git rebase main

이 작업은 feature-branchmain 브랜치의 최신 커밋을 기반으로 시작된 것처럼 보이게 합니다. 따라서, feature-branchmerge할 때 깔끔한 히스토리를 유지할 수 있습니다.

2) 커밋 정리

작업하는 동안 여러 개의 커밋을 생성했지만, 커밋 메시지를 수정하거나, 불필요한 커밋을 제거하고 싶을 때 interactive rebase를 사용합니다.

git rebase -i main

이 명령은 main 브랜치를 기준으로 interactive rebase를 시작합니다. interactive rebase는 각 커밋에 대해 pick, squash, fixup 등 다양한 작업을 수행할 수 있도록 해줍니다.

3) 코드 리뷰 전 정리

코드 리뷰를 받기 전에, 불필요한 커밋을 제거하고, 커밋 메시지를 다듬어, 코드 리뷰 과정을 더욱 원활하게 만들 수 있습니다. rebase를 사용하여 깔끔한 히스토리를 만들고, 코드 리뷰어에게 좋은 인상을 줄 수 있습니다.

7. rebase 관련 문제 해결

rebase를 사용하면서 발생할 수 있는 일반적인 문제들과 해결 방법에 대해 알아보겠습니다.

1) 충돌 해결 방법

rebase 중에 충돌이 발생하면, 다음과 같은 단계를 따라 해결할 수 있습니다.

  1. 충돌 표시 확인: 충돌이 발생한 파일을 열어, Git이 표시한 충돌 표시(<<<<<<<, =====<mark class="highlight">, >>>>>>>)를 확인합니다.
  2. 충돌 해결: 충돌 부분을 수동으로 수정하여, 원하는 결과를 만듭니다.
  3. git add: 수정된 파일을 스테이징 영역에 추가합니다.
  4. git rebase --continue: rebase를 계속 진행합니다.
  5. git rebase --abort: 문제가 발생하면, rebase를 중단하고, 원래 상태로 되돌립니다.

2) 실수로 rebase 취소했을 때

실수로 rebase를 취소했거나, rebase 과정에서 문제가 발생하여 중단된 경우, 다음과 같은 방법으로 복구할 수 있습니다.

  • git reflog: git reflog 명령을 사용하여, 최근에 수행한 모든 Git 작업을 확인합니다. rebase 이전의 상태로 되돌아가려면, 해당 시점의 커밋 해시를 찾아 git reset --hard <커밋 해시> 명령을 실행합니다.
  • git rebase --abort: 현재 rebase 작업을 중단하고, 원래 상태로 되돌립니다.
  • git rebase --skip: 충돌이 해결되지 않은 커밋을 건너뛰고, 다음 커밋으로 넘어갑니다. (주의: 이 방법은 변경 사항을 잃을 수 있으므로, 신중하게 사용해야 합니다.)

8. 결론

Git rebase는 브랜치를 효율적으로 관리하고 깔끔한 히스토리를 유지하는 데 매우 유용한 기능입니다. rebase의 개념, 작동 원리, 사용법, 주의사항을 충분히 이해하고, 적절한 상황에서 사용하면, 개발 생산성을 크게 향상시킬 수 있습니다. 하지만, 히스토리를 변경하는 기능이므로, 신중하게 사용하고, 특히 공개된 커밋에 대해서는 주의해야 합니다.== rebase의 장점과 단점을 정확히 이해하고, 코드 관리 스타일에 맞게 활용하는 것이 중요합니다.

비슷한 글 추천

Comments (0)

No comments yet. Be the first to comment!