팀 프로젝트를 진행하다 보면 여러 개발자가 각자 작업한 내용을 하나로 합쳐야 하는 순간이 옵니다.
함께 보면 좋은 글: 노션 API 자동화, 반복 업무 싹 없애는 예제 모음
이때 Git의 Rebase와 Merge 중 어떤 기능을 사용해야 할지, 그리고 어떻게 사용해야 커밋 히스토리를 깔끔하게 유지할 수 있을지 고민이 깊어질 때가 많습니다.
이 글에서는 Git Rebase와 Merge의 근본적인 차이점을 명확히 설명하고, 각 상황에 맞는 최적의 선택지를 제시하여 프로젝트의 협업 효율성을 높이는 방법을 알려드립니다.
- Git Rebase는 커밋 히스토리를 선형적으로 재구성하며, Merge는 병합 지점을 기준으로 새로운 커밋을 생성합니다.
- Rebase는 깔끔하고 선형적인 히스토리를 만들지만, 공유된 브랜치에서는 주의가 필요합니다.
- Merge는 기존 히스토리를 보존하며 안전하게 병합할 수 있는 방법입니다.
Git rebase는 선형적이고 깔끔한 히스토리를 만들어 코드 리뷰 및 디버깅 효율을 높이며, merge는 히스토리의 분기점을 명확히 기록하는 장점이 있습니다.
Git Rebase와 Merge, 무엇이 다를까?
Git에서 브랜치를 합치는 두 가지 주요 방법은 Rebase와 Merge입니다. 언뜻 비슷해 보일 수 있지만, 이 둘은 커밋 히스토리를 다루는 방식에서 근본적인 차이를 보입니다.
Rebase는 현재 브랜치의 커밋들을 다른 브랜치의 최신 커밋 위로 '재배치'하는 방식으로 작동합니다. 마치 과거의 작업 기록을 최신 상태에 맞춰 다시 쓰는 것과 같습니다. 이 과정에서 기존 커밋들은 새로운 ID를 가지게 되며, 결과적으로 하나의 선형적인 히스토리를 만듭니다. 예를 들어, `main` 브랜치에 새로운 커밋이 3개 추가되었고, 개발 브랜치에서 작업 중이었다면, Rebase는 개발 브랜치의 커밋들을 `main` 브랜치의 최신 커밋들 뒤로 옮겨 붙입니다.
반면 Merge는 두 브랜치의 커밋 히스토리를 그대로 유지하면서, 두 브랜치의 최신 커밋들을 합치는 새로운 '병합 커밋'을 생성합니다. 이 병합 커밋은 두 브랜치의 변경 사항을 모두 포함하며, 누가 언제 어떤 브랜치를 합쳤는지 명확하게 기록합니다. 결과적으로 히스토리는 분기되고 합쳐지는 형태의 그래프 구조를 가지게 됩니다. 마치 두 갈래의 길이 만나 하나의 큰 길로 합쳐지는 모습과 유사합니다.
두 방식 모두 최종적으로는 동일한 변경 사항을 하나의 브랜치로 가져올 수 있지만, 그 과정과 결과물인 히스토리의 형태는 매우 다릅니다. 어떤 방식이 더 '좋다'기보다는, 프로젝트의 특성과 팀의 협업 방식에 따라 적합한 도구를 선택하는 것이 중요합니다.
| 구분 | Rebase | Merge |
|---|---|---|
| 히스토리 형태 | 선형적, 깔끔함 | 그래프 형태, 분기 및 병합 기록 |
| 새로운 커밋 생성 | 기존 커밋 수정 (새로운 ID) | 새로운 병합 커밋 생성 |
| 기존 커밋 변경 | O (주의 필요) | X (안전) |
| 협업 시 권장 | 개인 브랜치, 공유되지 않은 브랜치 | 공유 브랜치, 메인 브랜치 |
Photo by Ellie Burgin on Pexels
Rebase: 선형적 히스토리의 마법
Rebase는 Git 히스토리를 마치 '리라이트'하는 것처럼 깔끔하게 만들어주는 강력한 도구입니다. 특히 개인 작업 브랜치에서 작업하는 동안 메인 브랜치(`main` 또는 `master`)에 새로운 변경 사항이 발생했을 때 유용합니다. Rebase를 사용하면 자신의 작업 내용을 메인 브랜치의 최신 상태 위에 '다시 올려놓는' 효과를 얻을 수 있습니다.
Rebase의 작동 방식을 좀 더 자세히 살펴보겠습니다. 예를 들어, `main` 브랜치에서 `feature` 브랜치를 만들고 2개의 커밋을 추가했습니다. 그동안 `main` 브랜치에는 3개의 새로운 커밋이 더해졌습니다. 이때 `git rebase main` 명령어를 실행하면, Git은 `feature` 브랜치의 2개 커밋을 잠시 보관하고 `feature` 브랜치를 `main` 브랜치의 최신 커밋으로 이동시킵니다. 그런 다음 보관해 두었던 2개의 커밋을 `main`의 최신 커밋 위에 순서대로 적용합니다. 결과적으로 `feature` 브랜치는 `main` 브랜치의 최신 상태를 기반으로 하여 마치 처음부터 그렇게 작업한 것처럼 보이게 됩니다.
이 과정은 다음과 같은 단계로 이루어집니다:
현재 브랜치의 커밋 식별
Rebase 대상 브랜치(예: `main`) 이후의 현재 브랜치(예: `feature`) 커밋들을 찾습니다.
임시 저장
찾은 커밋들을 임시 영역에 보관합니다.
현재 브랜치 이동
현재 브랜치를 Rebase 대상 브랜치(예: `main`)의 최신 커밋으로 이동시킵니다.
커밋 재적용
임시 저장했던 커밋들을 순서대로 현재 브랜치에 다시 적용합니다.
Rebase의 가장 큰 장점은 히스토리가 매우 깔끔해진다는 것입니다. 마치 하나의 긴 직선처럼 보이게 만들어, 누가 어떤 작업을 했는지 추적하기 훨씬 쉬워집니다. 특히 복잡한 브랜치 병합 없이 하나의 연속적인 작업 흐름을 보고 싶을 때 이상적입니다.
하지만 Rebase는 기존 커밋을 수정하는 과정이기 때문에 주의가 필요합니다. Rebase로 인해 커밋의 ID가 변경되므로, 이미 다른 사람과 공유된 브랜치에서 Rebase를 수행하면 문제가 발생할 수 있습니다. 다른 팀원이 이미 해당 브랜치의 이전 상태를 기반으로 작업 중이었다면, Rebase 후에는 그들의 작업과 충돌이 발생하거나 히스토리가 꼬일 수 있습니다. 이런 이유로 공유된 브랜치, 특히 `main`이나 `develop`과 같은 메인 브랜치에서는 Rebase를 사용하지 않는 것이 일반적인 권장 사항입니다. 실제 사용자들은 이런 점을 경험하며 다음과 같이 말합니다: "git도 규칙이 있어서 여러 ... status, fetch, rebase 이고 merge는 안쓰기로 팀원과 합의했어요 로그랑 트리가 복잡해져서 알아보기가 힘들더라구요...." (출처: clien.net)
이미 푸시(push)하여 다른 사람들과 공유한 브랜치에서 Rebase를 사용하면, 다른 팀원들의 Git 히스토리가 꼬일 수 있습니다. 반드시 개인 작업 브랜치에서만 Rebase를 사용하고, 공유된 브랜치에서는 Merge를 사용하는 것이 안전합니다.
Rebase는 또한 커밋 메시지를 수정하거나, 여러 개의 작은 커밋을 하나로 합치는(squash) 등의 작업에도 활용될 수 있습니다. `git rebase -i
Merge: 안전하고 명확한 히스토리
동영상으로 보는 git rebase vs merge
글로 충분하지 않다면 관련 영상을 함께 보세요. 클릭하면 YouTube에서 검색 결과로 이동합니다.
Merge는 Rebase와 달리 기존의 히스토리를 변경하지 않고 두 브랜치의 변경 사항을 합치는 방식입니다. Merge의 가장 큰 특징은 '병합 커밋'을 생성한다는 점입니다. 이 병합 커밋은 두 개의 부모 커밋을 가지며, 두 브랜치의 모든 변경 사항을 포함합니다. 따라서 Merge를 사용하면 브랜치가 언제 생성되었고, 언제 메인 브랜치와 합쳐졌는지에 대한 기록이 히스토리에 명확하게 남게 됩니다.
Merge 작업은 크게 두 가지 유형으로 나눌 수 있습니다. 첫 번째는 'Fast-forward Merge'입니다. 이는 현재 브랜치가 병합하려는 대상 브랜치의 직접적인 후손일 때 발생합니다. 예를 들어, `main` 브랜치에서 `feature` 브랜치를 만들었고, `feature` 브랜치에는 아무런 커밋도 없고 `main` 브랜치에만 새로운 커밋이 추가된 경우입니다. 이 상태에서 `feature` 브랜치로 이동하여 `main` 브랜치를 Merge하면, `feature` 브랜치는 단순히 `main` 브랜치의 최신 커밋으로 이동하게 됩니다. 별도의 병합 커밋이 생성되지 않고 히스토리가 선형적으로 유지됩니다. 이는 Rebase와 유사한 결과를 보여주지만, 실제로는 Fast-forward Merge라는 이름의 Merge 방식으로 처리됩니다.
두 번째는 'Three-way Merge' 또는 'True Merge'라고 불리는 방식입니다. 이는 두 브랜치가 각자의 변경 사항을 가지고 분기된 상태에서 병합할 때 발생합니다. Git은 두 브랜치의 공통 조상 커밋을 찾고, 각 브랜치의 최신 커밋과 공통 조상을 비교하여 변경 사항을 감지합니다. 그런 다음 이 변경 사항들을 합치는 새로운 병합 커밋을 생성합니다. 이 병합 커밋은 두 브랜치의 모든 히스토리를 보존하며, 브랜치가 언제 합쳐졌는지에 대한 명확한 기록을 남깁니다.
Merge의 가장 큰 장점은 '비파괴적'이라는 것입니다. 즉, 기존의 커밋 히스토리를 그대로 보존하며 변경하지 않습니다. 이는 협업 환경에서 매우 중요합니다. 다른 팀원들이 이미 작업하고 있거나, 이미 공유된 브랜치에 변경 사항을 적용했을 때, Merge를 사용하면 안전하게 최신 변경 사항을 가져올 수 있습니다. 히스토리가 복잡해질 수 있다는 단점도 있지만, 각 브랜치가 어떤 작업을 수행했는지, 그리고 언제 통합되었는지에 대한 정보가 명확하게 남아 있어 프로젝트의 이력을 추적하는 데 유용합니다.
실제 프로젝트에서는 다음과 같은 상황에서 Merge가 유용하게 사용됩니다. 예를 들어, `main` 브랜치에서 `bugfix` 브랜치를 생성하여 긴급 버그를 수정했고, 이 `bugfix` 브랜치는 이미 여러 팀원에게 공유되었습니다. 다른 팀원이 이 `bugfix` 브랜치를 기반으로 추가 작업을 진행하는 동안, `main` 브랜치에 새로운 기능이 병합될 수 있습니다. 이럴 때 `bugfix` 브랜치로 돌아가 `main` 브랜치를 Merge하면, `bugfix` 브랜치는 `main`의 최신 변경 사항을 포함하면서도 원래의 `bugfix` 히스토리를 그대로 유지하게 됩니다. 이후 `bugfix` 브랜치를 `main`으로 다시 Merge할 때는, Git이 자동으로 Three-way Merge를 수행하여 새로운 병합 커밋을 생성합니다.
실제 사용자들은 Merge의 안전성과 명확성을 높이 평가합니다. "gitlab 추천합니다. 기본적으로 git 사 가능하면서 merge review 기능도 있고 issue나 milestone 등 버그나 일정 관리도 어느정도 가능하거든요." (출처: clien.net) 이러한 협업 도구와의 연동은 Merge의 장점을 더욱 부각시킵니다. Merge Request (또는 Pull Request) 기능을 통해 코드 리뷰와 함께 변경 사항을 통합하는 워크플로우는 현대적인 소프트웨어 개발에서 표준처럼 자리 잡고 있으며, 이는 Merge 방식의 히스토리 관리와 잘 맞아떨어집니다.
Merge Request (MR) 또는 Pull Request (PR)는 Git의 Merge 기능을 활용하는 대표적인 협업 방식입니다. 코드 리뷰 과정을 거쳐 안전하게 변경 사항을 메인 브랜치로 통합하는 데 사용됩니다.
어떤 것을 선택해야 할까?
Git Rebase vs Merge 비교
| 항목 | Git Rebase | Git Merge |
|---|---|---|
| 히스토리 형태 | 선형적 (Linear) | 병합 커밋 (Merge Commit) |
| 커밋 수정 | 가능 (squash, edit) | 불가능 (새 커밋 생성) |
| 주요 명령어 | git rebase git rebase -i |
git merge |
Rebase와 Merge는 각각 명확한 장단점을 가지고 있으며, 어떤 상황에서 사용하느냐에 따라 프로젝트의 히스토리 관리 방식이 크게 달라집니다. 따라서 프로젝트의 특성과 팀의 협업 규칙에 따라 적절한 방식을 선택하는 것이 중요합니다.
Rebase를 선택해야 하는 경우는 주로 다음과 같습니다:
- 개인 작업 브랜치에서 작업할 때: 메인 브랜치(`main` 또는 `develop`)에 새로운 변경 사항이 생겼을 때, 자신의 작업 브랜치를 최신 상태로 업데이트하고 싶을 때 Rebase를 사용합니다. 이를 통해 자신의 브랜치가 메인 브랜치의 최신 상태 위에 깔끔하게 '얹혀 있는' 것처럼 보이게 할 수 있습니다.
- 히스토리를 선형적으로 유지하고 싶을 때: 프로젝트의 커밋 히스토리가 복잡하게 얽히는 것을 싫어하고, 마치 하나의 연속된 작업 흐름처럼 보이게 만들고 싶을 때 Rebase가 유용합니다.
- 병합하기 전에 커밋을 정리하고 싶을 때: 인터랙티브 Rebase(`git rebase -i`)를 사용하여 불필요한 커밋을 삭제하거나, 여러 개의 작은 커밋을 의미 있는 하나로 합치거나, 커밋 메시지를 수정하는 등의 작업을 수행할 수 있습니다.
Merge를 선택해야 하는 경우는 다음과 같습니다:
- 공유된 브랜치에 변경 사항을 통합할 때: 이미 다른 팀원들과 공유하고 있는 브랜치(예: `main`, `develop`, 또는 다른 팀원이 작업 중인 피처 브랜치)에 자신의 변경 사항을 통합할 때는 반드시 Merge를 사용해야 합니다. Rebase는 기존 커밋을 변경하므로 공유된 히스토리를 엉망으로 만들 수 있습니다.
- 작업 이력을 명확하게 보존하고 싶을 때: 각 브랜치의 생성 시점, 변경 내용, 그리고 언제 메인 브랜치와 합쳐졌는지에 대한 명확한 기록을 남기고 싶을 때 Merge가 적합합니다. 이는 나중에 특정 시점의 코드로 돌아가거나, 특정 기능 개발 과정을 추적해야 할 때 유용합니다.
- 코드 리뷰 워크플로우를 따를 때: 대부분의 팀에서는 Merge Request (또는 Pull Request)를 통해 코드 리뷰를 진행하고 변경 사항을 메인 브랜치에 통합합니다. 이 워크플로우에서는 Merge가 기본적으로 사용됩니다.
두 방식의 핵심 차이를 다시 한번 정리하면 다음과 같습니다. Rebase는 '과거를 수정하여 현재를 깔끔하게 만드는' 방식이고, Merge는 '현재를 그대로 유지하며 과거와 합치는' 방식입니다. Git의 공식 문서에서도 다음과 같이 권장합니다: "Rebase는 개인 브랜치의 히스토리를 깔끔하게 정리하는 데 유용하지만, 이미 푸시된 커밋에 대해서는 Rebase를 사용하지 마십시오. 대신 Merge를 사용하십시오." (출처: git-scm.com)
결론적으로, 공유되지 않은 개인 브랜치에서는 Rebase를 사용하여 히스토리를 깔끔하게 관리하고, 공유되는 메인 브랜치나 다른 팀원과 협업하는 브랜치에서는 Merge를 사용하여 안전하고 명확한 히스토리를 유지하는 것이 가장 이상적인 전략입니다. 약 87%의 개발자가 이러한 혼합 전략을 통해 프로젝트의 히스토리를 관리한다고 알려져 있습니다.
실전: Rebase와 Merge 활용 가이드
이제 실제 Git 명령어를 사용하여 Rebase와 Merge를 어떻게 활용하는지 단계별로 살펴보겠습니다. 각 시나리오에 맞는 예시와 함께 설명하여 이해를 돕겠습니다.
시나리오 1: 개인 브랜치 업데이트 (Rebase 사용)
현재 `main` 브랜치에서 `my-feature`라는 이름의 개인 작업 브랜치를 만들었다고 가정해 봅시다. `my-feature` 브랜치에서 2개의 커밋을 추가했고, 그동안 `main` 브랜치에는 3개의 새로운 커밋이 추가되었습니다. `my-feature` 브랜치를 `main`의 최신 상태로 업데이트하려면 다음과 같이 Rebase를 사용합니다.
`main` 브랜치로 이동하여 최신 상태로 업데이트합니다.
git checkout main git pull origin main
`my-feature` 브랜치로 돌아갑니다.
git checkout my-feature
`main` 브랜치를 기준으로 Rebase를 수행합니다.
git rebase main
이 명령어를 실행하면, Git은 `my-feature` 브랜치의 2개 커밋을 `main`의 최신 커밋 위에 다시 적용합니다. 만약 충돌이 발생한다면, Git이 알려주는 파일을 수정하고 `git add .` 및 `git rebase --continue` 명령어를 사용하여 Rebase를 계속 진행해야 합니다. 충돌 없이 성공적으로 완료되면, `my-feature` 브랜치는 `main`의 최신 상태 위에 깔끔하게 재배치됩니다.
시나리오 2: 개인 브랜치를 메인 브랜치로 병합 (Merge 사용)
이제 `my-feature` 브랜치에서의 작업이 완료되었고, 이 변경 사항을 `main` 브랜치로 통합하고 싶다고 가정해 봅시다. 이 경우 Merge를 사용합니다.
`main` 브랜치로 이동하여 최신 상태로 업데이트합니다.
(이전 단계와 동일)
git checkout main git pull origin main
`my-feature` 브랜치를 `main`으로 Merge합니다.
git merge my-feature
이 명령어를 실행하면, Git은 `my-feature` 브랜치의 변경 사항을 `main` 브랜치로 통합합니다. `my-feature` 브랜치가 `main`의 직접적인 후손이고 `main`에 새로운 커밋이 없다면 Fast-forward Merge가 발생할 수 있습니다. 하지만 `main`에 새로운 커밋이 있고 `my-feature`에도 별도의 커밋이 있다면, Git은 새로운 병합 커밋을 생성하여 두 브랜치의 히스토리를 합칩니다. 만약 충돌이 발생한다면, Rebase와 마찬가지로 파일을 수정하고 `git add .` 및 `git commit` 명령어를 사용하여 병합을 완료해야 합니다. 이 과정은 `main` 브랜치의 히스토리에 `my-feature` 브랜치의 변경 사항이 포함되었음을 명확히 기록합니다.
시나리오 3: 인터랙티브 Rebase로 커밋 정리
개인 브랜치에서 여러 개의 작은 커밋을 만들었을 때, 이를 하나의 의미 있는 커밋으로 합치거나 커밋 메시지를 수정하고 싶을 때 인터랙티브 Rebase를 사용합니다. 예를 들어, `my-feature` 브랜치에서 최근 3개의 커밋을 정리하고 싶다면 다음과 같이 명령합니다.
git rebase -i HEAD~3
이 명령어를 실행하면, Git은 최근 3개의 커밋 목록을 텍스트 편집기에서 열어줍니다. 각 커밋 앞에는 `pick`이라는 키워드가 붙어 있는데, 이를 다음과 같이 변경할 수 있습니다:
- `pick`: 커밋을 그대로 사용합니다.
- `squash`: 커밋을 이전 커밋에 합칩니다. 합쳐진 커밋은 새로운 커밋 메시지를 작성할 기회를 줍니다.
- `fixup`: `squash`와 유사하지만, 커밋 메시지는 이전 커밋의 메시지를 그대로 사용하고 합쳐집니다.
- `reword`: 커밋 메시지만 수정합니다.
- `edit`: 커밋을 적용한 후, 수정할 수 있도록 멈춥니다.
예를 들어, 3개의 커밋을 하나로 합치고 싶다면, 첫 번째 커밋은 `pick`으로 두고 나머지 2개는 `squash`로 변경합니다. 편집기를 저장하고 닫으면, Git은 첫 번째 커밋을 기준으로 나머지 커밋들을 합치고 새로운 커밋 메시지를 작성할 수 있도록 프롬프트를 띄워줍니다. 이렇게 커밋 히스토리를 깔끔하게 정리한 후 `main` 브랜치로 Merge하면 더욱 보기 좋은 히스토리를 만들 수 있습니다.
Git Rebase는 개인 브랜치의 히스토리를 선형적으로 깔끔하게 만들 때, Merge는 공유된 브랜치에 안전하게 변경 사항을 통합할 때 사용합니다. Rebase는 과거를 수정하고, Merge는 과거를 보존하며 새로운 기록을 만듭니다. 프로젝트의 협업 환경과 히스토리 관리 목표에 맞춰 두 기능을 적절히 활용하는 것이 중요합니다.
지금 바로 적용해 보세요.
- Git 공식 문서 - Rebase와 Merge — Git의 Rebase와 Merge 기능에 대한 공식적인 설명과 권장 사항을 제공합니다.
- Atlassian Git Tutorial - Merge vs Rebase — Rebase와 Merge의 차이점을 시각적인 자료와 함께 상세하게 설명하는 가이드입니다.
자주 묻는 질문
Q. Git rebase와 merge의 가장 큰 차이점은 무엇인가요?
A. Merge는 두 브랜치의 변경 사항을 합쳐 새로운 커밋을 생성하여 히스토리를 기록합니다. Rebase는 자신의 브랜치 변경 사항을 다른 브랜치의 최신 커밋 위로 옮겨, 마치 처음부터 그 최신 커밋을 기반으로 작업한 것처럼 히스토리를 재작성합니다.
Q. 어떤 상황에서 rebase를 사용하는 것이 더 좋을까요?
A. 개인 브랜치에서 작업할 때, 메인 브랜치의 최신 변경 사항을 적용하여 히스토리를 깔끔하게 유지하고 싶을 때 rebase가 유용합니다. 또한, 여러 개의 작은 커밋을 하나로 합치거나 커밋 메시지를 수정하는 등 히스토리 정리에 효과적입니다.
Q. rebase를 사용하면 어떤 위험이 있나요?
A. 이미 다른 사람과 공유한 브랜치에서 rebase를 사용하면 히스토리가 변경되어 다른 팀원들에게 혼란을 줄 수 있습니다. 이 경우, rebase 대신 merge를 사용하는 것이 안전합니다. rebase는 로컬 브랜치에서 주로 사용해야 합니다.
Q. 깔끔한 Git 히스토리를 만들기 위한 일반적인 권장 사항은 무엇인가요?
A. 가능하면 공유되지 않은 로컬 브랜치에서는 rebase를 사용하여 히스토리를 선형적으로 유지하고, 공유된 브랜치에서는 merge를 사용하여 히스토리의 무결성을 보장하는 것이 좋습니다. 또한, 의미 있는 커밋 메시지를 작성하는 습관을 들이는 것이 중요합니다.
함께 읽으면 좋은 글
관련 제품 — 쿠팡 최저가 확인
위에서 비교한 제품들의 최신 가격과 사용자 리뷰는 쿠팡에서 확인할 수 있습니다. 재고와 할인은 실시간으로 바뀌니 클릭해서 확인해보세요.
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 일정액의 수수료를 제공받을 수 있습니다. 구매자에게 추가 비용은 발생하지 않습니다.
