노트

머지와 리베이스

Merge vs. Rebase

인프라#git · 연결된 개념 4개

쉽게 말하면

머지는 갈라졌던 두 선로가 합류한 지점을 그대로 남기는 거고, 리베이스는 내 객차들을 떼어 상대 열차 맨 뒤에 다시 이어 붙이는 거예요. 머지는 실제로 일어난 일을, 리베이스는 일직선 기록을 남겨요.

비유가 깨지는 곳 옮겨 붙인 객차는 모양만 같은 새 객차라서 커밋 해시가 바뀌어요. 그래서 이미 푸시해 남과 공유한 커밋은 리베이스하지 않고, 로컬 최신화엔 리베이스, 공유 브랜치엔 머지를 흔히 써요.

두 브랜치의 작업을 합치는 두 방법이다. 머지는 히스토리를 그대로 두고 합치는 커밋을 하나 더 만들고, 리베이스는 내 커밋들을 상대 브랜치 끝 위로 다시 적용해 일직선 히스토리를 만든다.

머지

  • fast-forward(빨리 감기): 대상 브랜치가 갈라진 뒤 새 커밋이 없으면 새 커밋 없이 브랜치 포인터만 앞으로 옮긴다
  • --no-ff: 그런 경우에도 머지 커밋을 꼭 만든다. "이 기능 브랜치가 언제 들어왔는지"가 히스토리에 남는다
  • 장점은 실제로 일어난 일을 보존한다는 것, 단점은 머지 커밋이 쌓이면 그래프가 복잡해진다는 것

리베이스

  • 내 커밋을 새 기준 위에 하나씩 다시 만든다. 커밋 해시가 바뀐다
  • 히스토리가 깔끔해 blame·bisect로 따라가기 쉽다
  • 원칙: 이미 푸시해 남과 공유한 커밋은 리베이스하지 않는다. 다른 사람의 히스토리와 갈라져 충돌과 중복 커밋이 생긴다
git merge --no-ff feature
git rebase main            # 내 브랜치를 main 끝으로 옮기기
git pull --rebase          # 원격 갱신을 머지 커밋 없이 받기

고르는 기준

내 로컬 브랜치를 최신으로 맞출 때는 리베이스, 공유 브랜치에 기능을 합칠 때는 머지(필요하면 --no-ff)가 흔한 조합이다. 다른 기준 브랜치에서 시작했어야 하는 작업을 옮길 때도 git rebase --onto가 쓰인다. 커밋을 정리하는 일은 인터랙티브 리베이스로 커밋 정리, 되돌리기는 git reset (soft·mixed·hard)과 git revert를 본다. 결국 팀 규칙의 문제라 커밋 단위 합의와 함께 정한다.

출처: Pro Git: Rebasing

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 여러 저장소 합치기

    따로 관리하던 Git 저장소를 하나로 합칠 때, 히스토리를 버리지 않고 옮기는 방법이 두 가지 있다. 저장소 루트끼리 그대로 합치거나(unrelated histories 머지), 한쪽을 다른 쪽의 하위 폴더로 넣는다(subtree). 모노레포로 옮길 때 자주 쓴다.

  • 정리(Tidying)

    동작을 바꾸지 않는 아주 작은 구조 변경. 켄트 벡은 리팩터링이라는 말이 "기능 개발 중간의 긴 공사"처럼 쓰이며 동작 보존 원칙이 흐려지자, 더 작고 겁나지 않는 단위를 정리라는 이름으로 따로 불렀다. refactoring의 부분집합이다.

  • reflog로 날린 커밋 되살리기

    git reflog(reference log)는 HEAD와 브랜치가 가리킨 위치가 바뀐 기록을 시간순으로 보여준다. git log가 커밋 사이의 부모-자식 관계라면, reflog는 "내가 언제 어디에 있었나"의 기록이다.

  • 『켄트 벡의 Tidy First?』 개요

    켄트 벡이 "코드를 바꾸기 전에 먼저 정리해야 할까?"라는 질문 하나를 붙잡고 쓴 얇은 책. 아주 작은 구조 변경인 정리의 기법, 언제 정리할지의 관리, 왜 그런지의 이론을 차례로 다룬다.

  • 변경하기 쉬운 프런트엔드 코드

    Frontend Fundamentals는 "좋은 프런트엔드 코드 = 변경하기 쉬운 코드"라는 관점에서 가독성(Readability)·예측 가능성(Predictability)·응집도(Cohesion)·결합도(Coupling) 네 기준과 구체적인 기법을 정리한 공개 가이드다. 네 기준은 서로 부딪치기도 해서 상황에 맞게 무엇을 우선할지 고르는 것이 핵심이다.

보기 옵션