개요

Git은 단순한 버전 관리 도구를 넘어 강력한 히스토리 관리 기능을 제공합니다. Rebase로 깔끔한 커밋 히스토리를 유지하고, Cherry-pick으로 특정 변경을 정확히 가져오며, Bisect로 버그 도입 시점을 효율적으로 찾을 수 있습니다. 이 고급 기법들을 마스터하면 팀의 Git 워크플로우 품질이 크게 향상됩니다.

핵심 개념

Git 고급 명령어의 동작 원리를 이해하는 것이 중요합니다.

  • Rebase: 브랜치의 기반(base)을 변경하여 커밋 히스토리를 직선으로 정리
  • Interactive Rebase: 커밋 순서 변경, 합치기(squash), 메시지 수정, 분리 등 히스토리 재작성
  • Cherry-pick: 다른 브랜치의 특정 커밋만 현재 브랜치에 적용
  • Bisect: 이진 탐색으로 버그가 도입된 커밋을 자동으로 찾기
  • Reflog: 모든 HEAD 변경 기록을 추적, 실수로 삭제한 커밋 복구

실전 예제

Rebase를 활용한 히스토리 관리입니다.

# 기본 rebase: feature 브랜치를 main 최신으로 업데이트
git checkout feature/user-auth
git rebase main

# 충돌 발생 시
# 1. 충돌 파일 수정
# 2. git add .
# 3. git rebase --continue
# 취소하려면: git rebase --abort

# Interactive rebase: 최근 5개 커밋 정리
git rebase -i HEAD~5

# pick abc1234 feat: add login API
# squash def5678 fix: login typo          # 이전 커밋에 합침
# pick ghi9012 feat: add signup API
# reword jkl3456 feat: add auth middleware # 메시지 수정
# drop mno7890 wip: temporary debug code  # 커밋 삭제

# Rebase 후 강제 푸시 (자신의 브랜치에서만!)
git push --force-with-lease origin feature/user-auth

Cherry-pick으로 특정 커밋을 가져오는 예제입니다.

# 특정 커밋 하나를 현재 브랜치에 적용
git cherry-pick abc1234

# 여러 커밋을 연속으로 적용
git cherry-pick abc1234 def5678 ghi9012

# 범위 지정 (abc1234 제외, def5678 포함)
git cherry-pick abc1234..def5678

# 커밋하지 않고 변경사항만 가져오기
git cherry-pick --no-commit abc1234

# 핫픽스 시나리오: main의 버그 수정을 릴리스 브랜치에도 적용
git checkout release/v2.3
git cherry-pick main~2  # main의 2번째 이전 커밋 적용

# 충돌 발생 시
git cherry-pick --continue  # 충돌 해결 후 계속
git cherry-pick --abort     # 취소

Bisect로 버그 원인 커밋을 찾는 예제입니다.

# 수동 bisect
git bisect start
git bisect bad                # 현재 커밋이 버그 있음
git bisect good v2.0.0        # v2.0.0에서는 정상이었음

# Git이 중간 커밋을 checkout -> 테스트 후 판정
git bisect good               # 이 커밋에서는 정상
git bisect bad                # 이 커밋에서는 버그 있음
# ... 반복하면 원인 커밋을 찾음

# 자동 bisect (테스트 스크립트 활용)
git bisect start HEAD v2.0.0
git bisect run npm test       # 각 커밋에서 자동으로 테스트 실행

# bisect 종료 및 원래 브랜치로 복귀
git bisect reset

Reflog로 실수를 복구하는 예제입니다.

# reflog 확인
git reflog

# 출력 예시:
# abc1234 HEAD@{0}: rebase: finish
# def5678 HEAD@{1}: rebase: start
# ghi9012 HEAD@{2}: commit: important work

# rebase 전 상태로 복구
git reset --hard HEAD@{2}

# 삭제된 브랜치 복구
git reflog
git checkout -b recovered-branch abc1234

활용 팁

  • Rebase 황금 규칙: 이미 공유된(push된) 커밋은 절대 rebase하지 마세요. 자신의 로컬 브랜치에서만 사용하고, 공유 브랜치에는 merge를 사용합니다.
  • force-with-lease 사용: --force 대신 --force-with-lease를 사용하면 다른 사람이 push한 변경사항을 실수로 덮어쓰는 것을 방지할 수 있습니다.
  • 자동 Bisect 활용: 재현 가능한 버그라면 git bisect run으로 자동화하세요. 수백 개의 커밋에서도 O(log n)으로 원인을 찾을 수 있습니다.
  • 커밋 메시지 컨벤션: Interactive rebase로 정리할 때 Conventional Commits(feat:, fix:, chore:)를 적용하면 CHANGELOG 자동 생성에도 활용할 수 있습니다.
  • Reflog은 안전망: 실수로 커밋을 잃어버렸다면 30일 이내에 reflog에서 복구할 수 있습니다. 당황하지 말고 git reflog를 확인하세요.

마무리

Git의 고급 기법은 단순히 명령어를 아는 것을 넘어, 팀의 협업 품질과 코드 히스토리의 가독성에 직접적인 영향을 미칩니다. Rebase로 깔끔한 히스토리를 유지하고, Cherry-pick으로 정밀한 변경 관리를 하며, Bisect로 효율적인 디버깅을 수행하세요. 그리고 항상 Reflog가 안전망이 되어준다는 것을 기억하세요.