강의/Git & Github 실무 활용 완벽 가이드

Git Interactive Rebase: 히스토리 정리

studylida 2025. 3. 12. 10:20

Git Interactive Rebase란? – 히스토리를 정리하는 강력한 도구

Git을 사용하다 보면 작업이 쌓이며 커밋이 많아지고, 때로는 불필요한 커밋이 섞이기도 합니다. "일단 커밋하고 보자"는 식으로 올린 미완성 커밋이나, 버그가 포함된 커밋, 혹은 너무 자잘하게 나눠진 커밋들을 한눈에 보기 쉽도록 정리하고 싶을 때가 있죠.

이럴 때 유용한 Git의 강력한 기능이 바로 Interactive Rebase입니다. 기존의 커밋을 유지하는 것이 아니라, 커밋을 편집하고, 병합하고, 삭제하는 등 히스토리를 재구성할 수 있도록 도와주는 기능이죠.


Rebase의 두 가지 활용법

Git에서 rebase 명령어는 크게 두 가지 방식으로 활용됩니다.

  1. 머지(merge) 대체용: 기존 브랜치의 커밋을 새로운 브랜치의 끝으로 옮겨 깔끔한 히스토리를 유지하는 방식.
  2. 정리용(interactive rebase): 기존 커밋을 수정하고 정리하여, 마치 처음부터 깔끔하게 작업한 것처럼 히스토리를 다듬는 방식.

우리가 다룰 Interactive Rebase는 두 번째 경우에 해당합니다. 이 방법을 활용하면, 자신의 작업 브랜치에서 불필요한 커밋을 삭제하고, 커밋 메시지를 수정하며, 여러 개의 커밋을 합칠 수도 있습니다.

💡 단, 주의할 점!
Interactive Rebase는 자신의 로컬 작업 히스토리를 정리하는 용도로만 사용해야 합니다. 이미 다른 개발자들이 가져간 커밋을 수정하면, 충돌이 발생하고 협업에 혼란을 초래할 수 있습니다. 따라서 공유된 브랜치에서는 사용을 피해야 합니다.


Interactive Rebase의 기본 개념

Interactive Rebase를 사용할 때는 특정 커밋부터 현재 브랜치의 끝까지의 커밋을 대상으로 지정합니다.

git rebase -i HEAD~4

위 명령어는 최근 4개의 커밋을 대상으로 Interactive Rebase를 실행합니다. -i 옵션을 추가하면 인터랙티브 모드(interactive mode)가 활성화되어, 사용자가 원하는 방식으로 커밋을 수정할 수 있습니다.

🎯 Interactive Rebase를 활용하면 무엇을 할 수 있을까?

  • 커밋 메시지 변경하기 (reword)
  • 커밋을 수정하기 (edit)
  • 여러 개의 커밋을 합치기 (squash)
  • 커밋을 삭제하기 (drop)
  • 커밋 순서 변경하기

이러한 기능을 활용하면, 브랜치를 공유하기 전에 히스토리를 깔끔하게 정리할 수 있습니다.


Interactive Rebase의 핵심 동작 방식

  1. git rebase -i HEAD~4를 실행하면, 다음과 같은 편집 화면이 나타납니다.
     pick 123abc First commit
     pick 456def Second commit
     pick 789ghi Third commit
     pick 101jkl Fourth commit
  2. 이 화면에서 각 커밋 앞의 pick을 다른 명령어로 변경하여 원하는 작업을 수행할 수 있습니다.
  3. 변경을 완료한 후 저장하면, Git이 해당 내용에 맞게 히스토리를 재구성합니다.

왜 Interactive Rebase를 사용할까?

일반적으로 커밋을 자주 하는 것이 좋은 습관이지만, 너무 많은 커밋이 남아 있으면 히스토리가 지저분해집니다. 특히 버그가 포함된 커밋이나 의미 없는 커밋이 있다면, 공유하기 전에 정리하는 것이 좋습니다.

Interactive Rebase로 커밋 메시지 변경하기

Git에서 커밋 메시지를 작성할 때, 실수로 잘못된 표현을 쓰거나 프로젝트 가이드라인에 맞지 않는 메시지를 남길 수 있습니다.
예를 들어, 커밋 메시지를 명령형(Imperative Mood)으로 작성해야 하는데 실수로 과거형(Past Tense)으로 작성한 경우가 있을 수 있죠.

이럴 때 git commit --amend를 사용하여 바로 직전 커밋의 메시지를 변경할 수도 있지만,
더 이전의 커밋을 수정하고 싶다면?
👉 Interactive Rebase를 사용하면 해결할 수 있습니다! 🚀


커밋 메시지를 변경하는 방법

Interactive Rebase의 reword 명령어를 활용하면, 커밋의 내용은 그대로 둔 채 커밋 메시지만 수정할 수 있습니다.

📌 사용법

git rebase -i HEAD~[수정할 커밋 개수]

위 명령어를 실행하면 최근 [수정할 커밋 개수]만큼의 커밋을 대상으로 인터랙티브 리베이스 모드가 실행됩니다.
예를 들어, 최근 5개의 커밋 중 하나의 메시지를 수정하려면:

git rebase -i HEAD~5

실습: 커밋 메시지 변경하기

1️⃣ 커밋 이력 확인

먼저, git log --oneline을 실행하여 현재 커밋 이력을 확인합니다.

git log --oneline

출력 예시:

a1b2c3d Add new feature
e4f5g6 Fix login issue
h7i8j9 I added project files
k1l2m3 Initial commit

위에서 세 번째 커밋 "I added project files""Add project files"로 변경해보겠습니다.


2️⃣ Interactive Rebase 실행

git rebase -i HEAD~3

🎯 HEAD~3을 사용한 이유?

  • 최근 3개의 커밋이 대상이므로, "I added project files" 커밋을 포함할 수 있음.

3️⃣ reword 옵션 선택

명령어를 실행하면 다음과 같은 편집 화면이 나타납니다.

pick e4f5g6 Fix login issue
pick h7i8j9 I added project files
pick k1l2m3 Initial commit

여기에서 "I added project files" 커밋을 수정하고 싶다면, 해당 줄의 pickreword로 변경합니다.

pick e4f5g6 Fix login issue
reword h7i8j9 I added project files
pick k1l2m3 Initial commit

수정 후 저장하고 닫습니다. (Vim을 사용한다면 ESC:wqENTER)


4️⃣ 새로운 커밋 메시지 입력

이제 Git이 커밋 메시지를 수정할 수 있도록 텍스트 편집기를 띄웁니다.
현재 메시지가 보이며, 이를 원하는 메시지로 변경합니다.

# 기존 메시지
I added project files

아래처럼 변경

Add project files

변경 후 저장하고 편집기를 닫으면, Git이 리베이스를 진행합니다.


5️⃣ 변경 완료 및 확인

git log --oneline

출력 예시:

a1b2c3d Add new feature
e4f5g6 Fix login issue
h7i8j9 Add project files  # ✅ 변경됨!
k1l2m3 Initial commit

🎉 커밋 메시지가 성공적으로 변경되었습니다! 🚀


⚠️ 주의할 점

  1. 변경된 커밋 이후의 커밋 해시가 모두 변경됨
    • Git에서 커밋은 부모 커밋을 기준으로 해시가 생성됩니다.
    • 따라서 한 개의 커밋을 변경해도, 그 이후의 모든 커밋 해시가 변경됩니다.
    • 이를 피하기 위해 공유된 브랜치에서는 Interactive Rebase를 신중하게 사용해야 합니다.
  2. 수정한 커밋을 이미 Push한 경우?
    • 로컬에서 커밋 메시지를 수정했지만, 이미 원격 저장소(GitHub 등)에 Push한 상태라면?
      git push origin 브랜치이름 --force
    • --force 옵션을 사용해야 하지만, 강제 푸시는 협업 시 문제가 될 수 있으므로 주의해야 합니다.
    • 가능하면 공유된 브랜치에서는 rebase 대신 git commit --amend를 활용하는 것이 안전합니다.

🔎 정리

✅ Interactive Rebase의 reword를 사용하면 커밋 메시지만 수정할 수 있음
git rebase -i HEAD~[커밋 개수]를 사용하여 원하는 커밋을 선택 가능
✅ 커밋 메시지 수정 후 저장하면 새로운 커밋 해시가 생성됨
공유된 브랜치에서는 사용을 자제해야 함

 

 

 

 

Interactive Rebase로 커밋 수정 및 스쿼시(Squash)하기

소프트웨어 개발을 하다 보면, 하나의 기능을 개발하는 과정에서 여러 개의 커밋이 발생할 수 있습니다.
예를 들어, 다음과 같은 커밋 로그가 있다고 가정해봅시다.

a1b2c3d Add Bootstrap
e4f5g6 Forgot to add Bootstrap JavaScript
h7i8j9 Fix navbar typo
k1l2m3 Fix another navbar typo

이 커밋들을 보면,

  • "Add Bootstrap" 커밋에서 일부 파일을 빠트려서 "Forgot to add Bootstrap JavaScript"라는 추가 커밋이 발생했습니다.
  • 네비게이션 바(Navbar) 오타 수정을 두 번의 커밋에 걸쳐 진행했습니다.

이렇게 산발적으로 생긴 커밋들은 Git 히스토리를 어수선하게 만들고, 후에 작업 내용을 파악하기 어렵게 만듭니다.
✅ 해결 방법? Interactive Rebase를 이용한 커밋 병합(Squash & Fixup)!


🔎 Squash & Fixup의 차이

커밋을 병합하는 방법에는 SquashFixup 두 가지가 있습니다.

방법 설명 커밋 메시지
Squash (s) 여러 개의 커밋을 하나로 합치고, 커밋 메시지도 합쳐서 새 메시지 작성 가능 새 메시지 작성 가능
Fixup (f) 여러 개의 커밋을 하나로 합치지만, 첫 번째 커밋 메시지만 유지하고 나머지는 삭제 첫 번째 커밋 메시지만 남김

💡 언제 사용하면 좋을까?

  • Squash는 여러 커밋을 하나로 만들면서, 최종적으로 원하는 커밋 메시지를 정리할 때.
  • Fixup은 단순한 실수(오타 수정, 빠진 파일 추가 등)를 하나의 커밋으로 합칠 때.

🛠️ 실습: Interactive Rebase로 커밋 합치기

1️⃣ 커밋 로그 확인

우선, 현재 커밋 히스토리를 확인해 봅니다.

git log --oneline

출력 예시:

a1b2c3d Add Bootstrap
e4f5g6 Forgot to add Bootstrap JavaScript
h7i8j9 Fix navbar typo
k1l2m3 Fix another navbar typo

2️⃣ Interactive Rebase 실행

이제 Interactive Rebase를 실행하여, 병합할 커밋들을 선택합니다.

git rebase -i HEAD~4

🎯 HEAD~4를 사용한 이유?

  • 최근 4개의 커밋을 대상으로 rebase를 실행하려고 합니다.

3️⃣ Fixup을 이용해 커밋 병합

Interactive Rebase를 실행하면 다음과 같은 편집 화면이 나타납니다.

pick a1b2c3d Add Bootstrap
pick e4f5g6 Forgot to add Bootstrap JavaScript
pick h7i8j9 Fix navbar typo
pick k1l2m3 Fix another navbar typo

여기에서 "Forgot to add Bootstrap JavaScript" 커밋을 "Add Bootstrap" 커밋과 합치고 싶다면, pickfixup으로 변경합니다.

pick a1b2c3d Add Bootstrap
fixup e4f5g6 Forgot to add Bootstrap JavaScript
pick h7i8j9 Fix navbar typo
pick k1l2m3 Fix another navbar typo

이렇게 하면 "Forgot to add Bootstrap JavaScript" 커밋은 삭제되고, 해당 코드만 "Add Bootstrap" 커밋에 포함됩니다.
(즉, 메시지는 사라지고 코드만 유지됨!)

저장하고 편집기를 닫으면 Git이 자동으로 병합을 수행합니다.


4️⃣ Squash를 이용해 여러 커밋 하나로 합치기

이제 네비게이션 바(Navbar) 오타 수정 커밋 2개를 합쳐 보겠습니다.

pick a1b2c3d Add Bootstrap
fixup e4f5g6 Forgot to add Bootstrap JavaScript
pick h7i8j9 Fix navbar typo
squash k1l2m3 Fix another navbar typo

여기에서 picksquash로 변경하면,
"Fix navbar typo" 커밋과 "Fix another navbar typo" 커밋이 하나로 합쳐지면서 메시지도 함께 수정할 수 있습니다.

이후 커밋 메시지 수정 화면이 나타나면, 원하는 메시지로 정리하면 됩니다.

# This is a combination of multiple commits.
Fix navbar typo

저장 후 닫으면 두 개의 오타 수정 커밋이 하나로 병합됩니다.


5️⃣ 변경 확인

git log --oneline

출력 예시:

a1b2c3d Add Bootstrap
h7i8j9 Fix navbar typo

Bootstrap 관련 커밋은 하나로 정리됨
Navbar 오타 수정 커밋도 하나로 합쳐짐
Git 히스토리가 훨씬 깔끔해짐!


⚠️ 주의할 점

  1. Fixup & Squash를 사용하면 이후 커밋의 해시가 변경됨
    • Git에서 커밋은 부모 커밋을 기반으로 해시가 생성되므로,
      👉 Fixup/Squash를 수행하면 해당 커밋 이후의 모든 커밋 해시가 변경됩니다.
    • 따라서 공유된 브랜치에서 사용할 경우 주의해야 합니다.
  2. Push된 커밋을 변경했을 경우?
    • 이미 원격 저장소(GitHub 등)에 Push된 후 Fixup/Squash를 실행하면, 강제 푸시(--force)가 필요합니다.
      git push origin 브랜치이름 --force
    • ⚠️ 협업 중이라면 팀원들과 상의 후 강제 푸시하세요.

✅ 정리

✔️ Fixup (f): 커밋 코드는 유지하면서 메시지를 삭제하고 이전 커밋에 병합
✔️ Squash (s): 커밋을 합친 후, 메시지도 새롭게 작성 가능
✔️ Git 히스토리를 깔끔하게 정리할 때 매우 유용함
✔️ 이미 Push된 커밋을 수정할 경우 주의해야 함


🎯 이제 Git 히스토리를 깔끔하게 정리할 수 있습니다!

Interactive Rebase로 커밋 삭제(Drop)하기

소프트웨어 개발을 하다 보면, 실수로 의미 없는 커밋을 남기거나, 작업과 무관한 커밋이 들어가는 경우가 있습니다.
예를 들어, 다음과 같은 커밋이 있다고 가정해봅시다.

a1b2c3d Add new feature
e4f5g6 Fix login issue
h7i8j9 My cat accidentally committed nonsense
k1l2m3 Initial commit

이 중 "My cat accidentally committed nonsense"라는 커밋은 삭제하고 싶습니다.
✅ 해결 방법? Interactive Rebase를 이용한 커밋 드롭(Drop)!


🔎 Drop을 사용하면 어떻게 되나요?

Interactive Rebase의 drop 명령어를 활용하면, 커밋을 완전히 삭제할 수 있습니다.

방법 설명 커밋 코드
Fixup (f) 다른 커밋과 병합 (메시지 삭제) 유지
Drop (d) 커밋 자체를 삭제 삭제됨

💡 언제 사용하면 좋을까?

  • 실수로 잘못된 코드가 포함된 커밋을 제거하고 싶을 때
  • 불필요한 커밋이 포함되어 Git 히스토리를 정리하고 싶을 때

🛠️ 실습: Interactive Rebase로 커밋 삭제하기

1️⃣ 커밋 로그 확인

우선, 현재 커밋 히스토리를 확인해 봅니다.

git log --oneline

출력 예시:

a1b2c3d Add new feature
e4f5g6 Fix login issue
h7i8j9 My cat accidentally committed nonsense
k1l2m3 Initial commit

2️⃣ Interactive Rebase 실행

이제 Interactive Rebase를 실행하여, 삭제할 커밋을 선택합니다.

git rebase -i HEAD~3

🎯 HEAD~3을 사용한 이유?

  • 최근 3개의 커밋을 대상으로 rebase를 실행하려고 합니다.

3️⃣ Drop을 이용해 커밋 삭제

Interactive Rebase를 실행하면 다음과 같은 편집 화면이 나타납니다.

pick a1b2c3d Add new feature
pick e4f5g6 Fix login issue
pick h7i8j9 My cat accidentally committed nonsense

여기에서 "My cat accidentally committed nonsense" 커밋을 삭제하고 싶다면, pickdrop으로 변경합니다.

pick a1b2c3d Add new feature
pick e4f5g6 Fix login issue
drop h7i8j9 My cat accidentally committed nonsense

이렇게 하면 "My cat accidentally committed nonsense" 커밋은 Git 히스토리에서 완전히 삭제됩니다.

저장하고 편집기를 닫으면 Git이 자동으로 커밋을 제거합니다.


4️⃣ 변경 확인

git log --oneline

출력 예시:

a1b2c3d Add new feature
e4f5g6 Fix login issue
k1l2m3 Initial commit

불필요한 커밋이 깔끔하게 사라졌습니다! 🚀


⚠️ 주의할 점

  1. Drop을 사용하면 해당 커밋의 코드도 삭제됨
    • fixup은 코드가 유지되지만 drop은 커밋 자체를 삭제합니다.
    • 따라서 중요한 코드가 포함된 커밋을 삭제할 경우 주의해야 합니다.
    • 실수로 삭제했다면 git reflog를 사용해 복구할 수도 있습니다.
  2. Push된 커밋을 삭제했을 경우?
    • 이미 원격 저장소(GitHub 등)에 Push된 후 Drop을 실행하면, 강제 푸시(--force)가 필요합니다.
      git push origin 브랜치이름 --force
    • ⚠️ 협업 중이라면 팀원들과 상의 후 강제 푸시하세요.

✅ 정리

✔️ Drop (d): 커밋 자체를 삭제
✔️ 불필요한 커밋을 Git 히스토리에서 제거할 때 유용
✔️ 이미 Push한 커밋을 삭제할 경우 주의해야 함


🎯 이제 Git 히스토리를 깔끔하게 정리할 수 있습니다!

이제 Interactive Rebase를 활용해 커밋 메시지 수정, 커밋 병합(Squash & Fixup), 그리고 불필요한 커밋 삭제까지 마스터했습니다. 🚀