협업을 진행하며 브랜치를 생성하고 git merge로 코드를 병합하다 보면, 수많은 병합 커밋(Merge Commit)이 생성되어 커밋 히스토리가 거미줄처럼 복잡해집니다. 프로젝트의 규모가 커질수록 누가 언제 어떤 목적으로 코드를 변경했는지 한눈에 파악하기가 매우 어려워집니다. 이러한 문제를 해결하고 마치 한 사람이 순차적으로 개발한 것처럼 깔끔한 일직선 히스토리를 만들어주는 강력한 도구가 바로 Git Rebase입니다.
이번 포스팅에서는 Rebase의 작동 원리와 git merge와의 결정적인 차이점, 그리고 실무에서 Rebase를 사용할 때 반드시 지켜야 할 주의사항에 대해 자세히 알아보겠습니다.

1. Rebase란 무엇인가?
Rebase라는 단어는 'Base(기준점)를 Re(다시) 설정한다'는 의미를 가지고 있습니다. 내가 작업 중인 브랜치가 처음 파생되었던 원래의 분기점(과거의 커밋)을 버리고, 다른 브랜치(주로 최신 master 브랜치)의 가장 끝단 커밋을 새로운 분기점으로 삼아 내 작업 내역을 그 위에 이어 붙이는 작업입니다.
Rebase의 작동 원리
예를 들어 master 브랜치에서 파생된 feature 브랜치에서 두 개의 커밋을 추가했다고 가정해 보겠습니다. 그 사이 다른 팀원이 master 브랜치에 새로운 커밋을 추가했습니다. 이때 feature 브랜치를 master로 Rebase하면 Git은 다음 작업을 수행합니다.
feature브랜치의 커밋 내역(패치)을 임시 공간에 저장합니다.feature브랜치가 가리키는 커밋을 최신master커밋으로 옮깁니다(Base 변경).- 임시로 저장해 두었던
feature브랜치의 커밋들을 최신master위에서부터 하나씩 순서대로 다시 적용하여 새로운 커밋들을 생성합니다.
결과적으로 브랜치가 갈라졌던 흔적이 사라지고, 마치 feature 브랜치의 작업이 최신 master 코드 위에서 방금 시작된 것처럼 일직선의 히스토리가 만들어집니다.
2. Rebase 수행하기
Rebase를 수행하는 방법은 병합과 방향성이 반대입니다. master에 feature를 흡수시키는 Merge와 달리, 내 feature 브랜치를 master 위에 얹어달라고 요청하는 형태이므로 내가 작업 중인 브랜치에서 실행해야 합니다.
# 1. 내가 작업 중인 브랜치로 이동
$ git switch feature
# 2. master 브랜치를 새로운 베이스로 설정하여 rebase 진행
$ git rebase master
Successfully rebased and updated refs/heads/feature.
Rebase가 성공적으로 끝나면 히스토리는 일직선이 되지만, 아직 master 브랜치의 포인터는 뒤쳐져 있는 상태입니다. 따라서 master 브랜치로 이동한 후, 방금 Rebase된 feature 브랜치를 Fast-forward Merge로 합쳐주어야 모든 작업이 완료됩니다.
# 3. master 브랜치로 이동
$ git switch master
# 4. feature 브랜치를 병합 (무조건 Fast-forward 병합이 발생함)
$ git merge feature
Updating 1a2b3c..9d8e7f
Fast-forward
3. Merge vs Rebase 비교
두 명령어 모두 서로 다른 두 브랜치의 코드를 하나로 합친다는 최종 목적은 동일하지만, 그 결과물인 '히스토리'의 형태가 전혀 다릅니다.
- Merge의 장점: 브랜치가 언제 분기되었고 언제 병합되었는지 실제 발생한 시간 흐름 그대로 기록됩니다. 정보의 손실이 없고 직관적입니다.
- Merge의 단점: 커밋 내역이 지저분해지고 복잡해져, 나중에 버그가 발생한 원인 커밋을 찾기(추적) 매우 힘듭니다.
- Rebase의 장점: 프로젝트의 전체 히스토리가 한 줄로 매우 깔끔하게 정리됩니다. 코드 리뷰어 입장에서 논리적인 흐름을 파악하기 좋습니다.
- Rebase의 단점: 충돌이 발생할 경우 각각의 커밋을 적용할 때마다 반복해서 충돌을 해결해 주어야 하는 번거로움이 있습니다.
4. Rebase의 절대 원칙 (주의사항)
"이미 원격 저장소(Remote)에 Push한 커밋은 절대 Rebase 하지 마라!"
Rebase는 기존 커밋을 단순히 이동시키는 것이 아니라, 내용이 같더라도 해시값이 완전히 다른 새로운 커밋을 새로 찍어내는 작업입니다. 만약 다른 팀원들이 이미 원격 저장소에서 내려받아 사용하고 있는 커밋을 내가 로컬에서 Rebase로 수정해버린 후 억지로 원격에 덮어씌운다면(Force Push), 다른 팀원들의 저장소와 히스토리가 완전히 꼬여버리는 대참사가 발생합니다. Rebase는 오로지 내 로컬 컴퓨터에만 존재하여 아무도 모르는 커밋들을 깔끔하게 정리할 때만 사용해야 합니다.
1. 작업 임시 보관소: git stash
어떤 브랜치에서 파일을 수정하던 중에 아직 커밋할 단계는 아니지만, 급하게 다른 브랜치로 넘어가야 할 상황이 발생했다고 가정합시다. 변경된 파일이 워킹 디렉토리에 남아있는 상태로 브랜치를 전환하면 충돌이 발생하거나 코드가 섞이는 문제가 생깁니다. 이때 수정 중인 내역을 서랍에 잠시 넣어두고 워킹 디렉토리를 깨끗하게 비워주는 명령어가 바로 git stash입니다.
# 1. 현재 수정 중인 파일들을 임시 보관소(서랍)에 넣음
$ git stash
Saved working directory and index state WIP on master: a1b2c3d docs: README 수정
# 2. 이제 워킹 디렉토리는 깨끗해졌으므로 다른 브랜치로 안전하게 이동 가능
$ git switch bugfix-branch
# 3. 다른 브랜치에서 급한 불을 끄고 커밋 완료 후 다시 원래 브랜치로 복귀
$ git switch master
# 4. 서랍에 넣어두었던 작업 내역을 다시 꺼내서 이어서 작업
$ git stash pop
git stash pop은 저장해둔 작업을 꺼내옴과 동시에 임시 보관함 목록에서 해당 내역을 지워줍니다. 만약 여러 개의 작업을 스태시 해두었다면 git stash list로 목록을 확인하고, git stash apply stash@{0}과 같이 특정 내역을 지정하여 적용할 수도 있습니다.
2. 시간을 되돌리는 git reset
git reset은 브랜치의 포인터를 과거의 특정 커밋으로 강제로 옮겨버리는 강력한 명령어입니다. 시간을 아예 되돌려서, 잘못 커밋된 내역들을 역사 속에서 지워버리고 싶을 때 사용합니다. reset 명령어는 되돌리는 수준에 따라 3가지 옵션을 제공합니다.
- --soft: 브랜치의 위치만 과거로 이동하고, 그 이후에 수정되었던 파일들의 내용은 워킹 디렉토리와 스테이징 영역(Index)에 그대로 유지됩니다. 단순히 커밋 기록만 취소하고 바로 다시 커밋할 때 유용합니다.
- --mixed (기본값): 브랜치의 위치가 과거로 이동하며, 파일들의 수정 내용은 워킹 디렉토리에만 남고 스테이징 영역에서는 내려옵니다(Unstaged). 어떤 파일을 커밋할지 처음부터 다시 고르고 싶을 때 사용합니다.
- --hard: 브랜치의 위치는 물론이고, 워킹 디렉토리의 수정 내용까지 과거 커밋 상태로 완벽하게 덮어씁니다. 돌아간 시점 이후의 작업 내용은 완전히 삭제되므로 사용 시 극도의 주의가 필요합니다.
# 가장 최근 커밋 1개를 취소하되, 수정했던 파일 내용은 워킹 디렉토리에 그대로 남김 (기본 mixed 옵션 적용)
$ git reset HEAD~1
# 특정 해시값(a1b2c3d) 시점으로 되돌리며, 그 이후의 변경 사항은 모두 영구 삭제함 (경고)
$ git reset --hard a1b2c3d
3. 이력을 남기며 취소하는 git revert
git reset은 과거의 이력을 아예 삭제해 버리기 때문에, 이미 원격 저장소(GitHub)에 Push하여 다른 사람들과 공유된 커밋을 Reset해 버리면 협업에 심각한 문제가 발생합니다. 이럴 때는 과거 이력을 지우지 않고, "이전 커밋의 작업을 취소하는 새로운 커밋"을 만들어내는 git revert를 사용해야 합니다.
# 취소하고 싶은 특정 커밋의 해시값 입력
$ git revert 9d8e7f
[master b8c9d0e] Revert "feat: 잘못 만든 기능 추가"
1 file changed, 10 deletions(-)
위 명령어를 실행하면 Git은 9d8e7f 커밋에서 추가되었던 코드는 삭제하고, 삭제되었던 코드는 추가하는 반대 동작을 수행한 뒤 새로운 커밋(위의 b8c9d0e)을 생성합니다. 히스토리에 "이전에 잘못된 코드가 있었고, 이를 취소(Revert)했다"는 명확한 이력이 남기 때문에 원격 저장소에 이미 올라간 코드를 되돌릴 때는 반드시 Revert를 사용해야 합니다.
'CI.CD > GIT' 카테고리의 다른 글
| [GIT] Git 디버깅(Blame, Bisect)과 실무 브랜치 전략(Git Flow) (0) | 2026.08.07 |
|---|---|
| [GIT] 커밋 정밀 조작(Amend, Cherry-pick)과 최후의 복구 도구(Reflog) (0) | 2026.08.07 |
| [GIT] Git 브랜치(Branch) 완벽 이해와 병합 충돌(Conflict) 해결 (0) | 2026.08.07 |
| [GIT] 커밋 히스토리 관리 및 원격 저장소(GitHub) 협업 (0) | 2026.08.07 |
| [GIT] Git 시작하기와 로컬 워크플로우 완벽 가이드 (0) | 2026.08.07 |