프로젝트에서 어떤 브랜칭 전략을 쓰더라도, 브랜치 간에 코드 변경 사항을 통합하는 작업은 거의 매일 하게 됩니다. Git에서는 이를 병합(merge)하거나 리베이스(rebase)하는 두 가지 주요 방법이 있습니다.
이 글에서는 두 방법을 애니메이션을 통해 보여주며, 각각의 차이점과 실제로 적용할 때 주의해야 할 점을 알아보겠습니다.
Git 공식 매뉴얼에 따르면, rebase는 “다른 기반(base) 브랜치 위에 커밋들을 다시 적용(reapply)한다”고 설명하고 있고, merge는 “두 개 이상의 개발 히스토리를 한데 합친다”라고 되어 있습니다.
즉, merge는 “일어난 그대로의 히스토리를 유지”하는 반면, rebase는 “히스토리를 재작성(rewrite)한다”는 점이 두 방법의 가장 큰 차이입니다.
가장 흔히 사용하는 변경 사항 통합 방식인 병합(merge)부터 살펴보겠습니다. 개발자 A가 개발자 B가 작업한 변경 사항을 feature-2 브랜치에 병합하기 전에, 우선 뒤처져 있는 로컬 master를 업데이트해야 합니다. 그리고 나서 master와 원격 저장소 master(o/master)가 동기화되면, 개발자 A는 자신의 토픽 브랜치에 모든 변경 사항을 문제없이 병합할 수 있게 됩니다.

출처: Differences Between Git Merge and Rebase — And Why You Should Care
모든 변경 사항이 feature-2 브랜치에 병합되었으므로, 개발자 A는 이제 이 브랜치를 계속 개발할 수 있고, 작업이 완료되면 master 브랜치에 다시 병합하여 마무리할 수 있게 되었습니다.
아래는 병합 작업 후의 최종 결과입니다. 보시다시피, C7 커밋만 새로 추가되었고, 전체 개발 히스토리는 발생한 그대로 그대로 유지됩니다.
병합 워크플로우를 이해했다면, 이제 같은 예제를 리베이스 관점에서 살펴볼 차례입니다.
병합과 마찬가지로, 개발자 A가 변경 사항을 통합하기 전에 먼저 로컬과 원격 저장소의 master 브랜치를 동기화해야 합니다. 그 후, “일어난 그대로의 히스토리를 보존”하는 일반적인 병합 대신, 리베이스로 모든 변경 사항을 재배치해 히스토리를 “재작성(rewrite)”할 수 있습니다.
feature-2 브랜치를 master에 리베이스하면, Git은 C5와 C6 커밋을 차례대로 되감아(rewind) 다시 C4 위에 적용합니다. 이렇게 하면 feature-2 브랜치가 마치 개발자 B의 완료된 변경 사항 최종 지점에서 분기된 것처럼 깔끔한 히스토리를 갖게 됩니다.

출처: Differences Between Git Merge and Rebase — And Why You Should Care
모든 변경 사항이 다시 통합되었으므로, 개발자 A는 이제 토픽 브랜치에서 계속 작업을 이어갈 수 있게 되었습니다.
아래는 리베이스 작업 후의 최종 결과입니다. 보시다시피, C5와 C6 커밋이 C4 위로 그대로 재적용되면서 기존 커밋이 완전히 사라지고 개발 히스토리가 재작성되었습니다.

앞서 리베이스는 히스토리를 재작성하고, 머지는 히스토리를 보존한다고 했습니다. 그렇다면 좀 더 넓은 관점에서 이것이 갖는 의미는 무엇일까요? 그리고 이 두 가지 작업이 제공하는 가능성과 잠재적 단점은 무엇일까요?
예를 들어 변경 사항을 통합하는 과정에서 까다로운 충돌이 발생했다고 가정해 봅시다.
머지를 사용했다면, C7 커밋 안에서 한 번만 충돌을 해결하면 됩니다.
리베이스를 사용했다면, C5와 C6이 하나씩 다시 적용되는 과정에서 비슷한 충돌을 여러 번 해결해야 할 수도 있습니다.
만약 충돌이 너무 복잡해지거나 잦다면, 같은 파일을 여러 사람이 동시에 오래 작업하면서 서로 충분히 소통하지 않았을 가능성을 의심해 볼 수 있습니다.
또 다른 리베이스 관련 문제는, 리베이스하려는 브랜치가 이미 원격 저장소에 올라가 있고, 다른 사람이 그 브랜치를 기반으로 작업하고 있을 때 발생합니다. 이런 상황에서 리베이스된 브랜치는 참여자 모두에게 큰 혼란을 줄 수 있습니다. Git이 “당신의 브랜치가 동시에 앞서 있고, 뒤처져 있다”고 말해 버릴 수 있기 때문입니다.
이런 문제가 생기면, git pull --rebase 명령어로 원격 변경 사항을 가져오는 방법이 대체로 문제를 해결해 줍니다.
게다가 원격에 이미 공개된 브랜치를 리베이스해야 할 때(다른 사람이 그 브랜치를 기반으로 작업하지 않았더라도), 변경 내용을 원격에 반영하려면 강제 푸시(force push) 가 필요합니다. 이 과정에서 기존 원격 참조(remote reference)는 완전히 덮어쓰이게 됩니다.
마지막으로, 머지는 히스토리를 보존하고 리베이스는 히스토리를 재작성하기 때문에, 리베이스를 진행하다 보면 실제로 데이터를 잃을 수도 있습니다. 새 커밋을 다시 적용하는 순간, 예전 커밋은 시간이 지나 가비지 컬렉션이 이루어지면 완전히 삭제됩니다.
리베이스와 관련된 자주 발생되는 이슈들을 피하기 위해서는 다음과 같은 규칙을 지키는 편이 좋다.
다만.. 혼자 작업을 하는 깃이면 상관없다. 안전하게 force push 할 수 있기 때문이다.
이는 리베이스 후 결과물을 쉽게 비교할 수 있게 해주고 필요 시 리베이스 전 상태로 돌아갈 수 있게 해준다.
https://git-scm.com/book/ko/v2/Git-%EB%B8%8C%EB%9E%9C%EC%B9%98-Rebase-%ED%95%98%EA%B8%B0