
협업하다 보면 "develop 최신 반영"이 필요할 때가 많다. 이때 흔히 쓰는 명령이 git pull인데, 사실 git pull은 두 가지 방식으로 동작할 수 있다.
git pull : fetch + mergegit pull --rebase : fetch + rebase둘 다 "원격 변경을 가져온다"는 점은 같지만, 커밋 히스토리가 완전히 달라진다. 차이를 정확히 알아야 실수하지 않을 수 있기 때문에, 꼼꼼히 정리를 해보려 한다.
git fetch origin
git merge origin/develop
현재 브랜치가 원격 브랜치보다 뒤처져만 있는 상태라면(fast-forward한 상태라면)
merge commit 없이, 브랜치 포인터만 앞으로 이동한다.
A - B - C (origin/develop)
↑
develop (local)
이 경우:
로컬 브랜치에 독립적인 커밋이 이미 존재하면(갈라진 경우)
merge 시 merge commit이 새로 생성된다.
예시:
A - D - E (origin/develop) (내가 분기했던 A 상태 이후로 D, E가 더 붙음)
\
B - C (local feature)
pull(merge) 후:
A - D - E -----
\ \
B - C -------M (M = merge commit)
이 경우:
✅ 장점
⚠️ 단점
📍 요약
git fetch origin
git rebase origin/develop
앞선 예시와 같은 상태에서 시작한다고 가정하면:
A - D - E (origin/develop)
\
B - C (local feature)
git pull --rebase 후:
A - D - E - B' - C'
이때의 핵심은:
B, C 커밋이 그대로 유지되는 것이 아니라B', C'로 다시 생성됨이 경우:
✅ 장점
⚠️ 단점 (중요)
B, C 커밋 대신B', C'라는 새로운 커밋을 만들어서 붙임B', C' 커밋을 만들어 붙여버렸기 때문에.)📍 요약
git pull --rebase는보통 merge 방식의 pull을 사용했다면, merge conflict를 해결하고 마지막에 한 번 머지 커밋을 남기는 방식에 익숙할 것이다.
하지만 rebase는 다르다. 각 커밋을 순서대로 다시 적용하는 과정을 진행하게 된다.
커밋 단위로 충돌을 해결해야 한다.
merge 충돌 (한 번의 충돌 → 한 번의 merge commit)
충돌 해결 → git add → git commit(merge commit 생성)
rebase 충돌 (커밋 재적용 중 충돌 발생 시 → 해당 커밋에서 해결 후 계속)
충돌 해결 → git add → git rebase --continue
vscode로 rebase 충돌을 해결해보자.
| branch | 커밋 히스토리 |
|---|---|
develop | test 4 → rebase test4 → rebase test5 → rebase test6 |
chore/rebase-test | test 4 → rebase test1 → rebase test2 → rebase test3 |
인 상태에서
chore/rebase-test 브랜치에서 git pull --rebase origin develop을 하게 되면
다음과 같이 컨플릭트가 발생한다.
보면 컨플릭트를 해결한 후 git add 또는 rm으로 충돌 파일들을 스테이징하고
git rebase --continue를 통해 다음 rebase를 진행하라는 것을 알 수 있다.
혹은 스킵하고 싶다면 git rebase --skip을, 중단하고 싶다면 git rebase --abort를 사용하면 된다.
충돌을 해결해보자. 먼저 rebase test1 커밋 시점에서의 충돌만 나온다.
하던 대로 충돌을 해결해주면 된다.
충돌을 해결한 파일을 추가하고 git rebase를 이어가보자.
git add a
git rebase --continue
그러면 현재 rebase 중인 커밋(test1)을 다시 적용하면서 사용할 커밋 메시지를 확인/수정할 수 있다. 수정이 필요 없는 경우 그냥 그대로 q로 나가주면 된다.
그럼 다음 rebase가 진행된다.
...
그렇게 쭉 진행하면 rebase가 끝나게 된다!
처음 깃 히스토리와 비교해보면
| rebase 전 | rebase 후 |
|---|---|
![]() | ![]() |
커밋 해시가 바뀐 걸 볼 수 있다. 대신 선형 커밋 상태가 되며 머지 커밋이 따로 남지 않아 히스토리가 깔끔해진 것을 볼 수 있다!
추천: git pull --rebase origin develop
git checkout feature/my-work
git fetch origin
git rebase origin/develop
추천: git pull(merge)
(히스토리 재작성 없이 안전)
git checkout develop
git pull origin develop
git pull과 git pull --rebase를 정리하며 내린 나름의 결론은
feature 브랜치는 rebase 방식으로 develop의 최신 상태를 반영하는 것이 좋겠다는 거다.
feature 브랜치는 보통 개인 작업용 브랜치이고, 다른 사람이 기반으로 삼지 않은 경우가 대부분이다.
이 경우 커밋 히스토리를 보존하는 것보다, 불필요한 merge 커밋 없이, 히스토리를 깔끔하게 유지하고 변경 내용을 명확히 보는 것이 더 좋다고 느꼈다.
하지만 커밋을 아예 새로 만들어 이어붙이는 명령어인만큼 주의해서 사용하자!