Published on

Git rebase 후 PR 커밋 중복? 해결 6단계

Authors

서로 다른 브랜치 히스토리를 정리하려고 git rebase를 썼는데, PR을 열어보니 이미 머지한 커밋이 또 보이거나, 커밋 개수가 갑자기 늘고, 리뷰 코멘트가 엉뚱한 줄에 달리는 상황을 겪는 경우가 있습니다.

이 현상은 “내가 뭘 잘못했나?”라기보다, rebase가 커밋 SHA를 바꾸는 동작이고, PR 도구(GitHub/GitLab 등)가 기준 브랜치와 비교하는 방식 때문에 생기는 전형적인 증상입니다. 이 글에서는 원인부터 안전하게 복구하는 방법까지, 실제 팀 개발에서 바로 적용 가능한 6단계 해결 절차로 정리합니다.

문제 해결 글을 자주 쓰다 보면 공통점이 하나 있습니다. 장애든, 빌드 캐시든, Git이든 결국 “관찰 → 원인 분리 → 안전한 복구”가 핵심입니다. 비슷한 접근이 궁금하면 Docker 빌드가 느릴 때 BuildKit 캐시 깨짐 복구도 참고해보세요.

왜 rebase 후 PR에 커밋이 중복되어 보일까?

핵심만 먼저 정리하면 아래 3가지가 가장 흔합니다.

  1. rebase는 커밋을 복사해서 새로 만든다

    • 같은 내용이라도 커밋 SHA가 달라집니다.
    • PR 화면에서는 “새 커밋”으로 인식될 수 있습니다.
  2. PR의 base branch가 내가 생각한 것과 다르다

    • 예: 원래 develop 기준 PR이어야 하는데 main 기준으로 열려 있거나, 반대로 되어 있으면 이미 포함된 커밋이 다시 보입니다.
  3. merge commit / squash / rebase merge 전략이 섞여 히스토리가 갈라진다

    • 어떤 브랜치는 merge commit으로 합쳐졌고, 어떤 브랜치는 rebase로 정리되면 “공통 조상” 계산이 예상과 달라져 diff가 커질 수 있습니다.

중요 포인트: PR 도구는 보통 “내 브랜치에만 있는 커밋”을 보여주려 하지만, 실제로는 공통 조상(merge-base) 기준으로 비교합니다. 이 merge-base가 바뀌면 커밋이 중복처럼 보이거나 diff가 폭증할 수 있습니다.

해결 6단계 (안전하게 PR 정상화)

아래 절차는 “원인 확인 → 올바른 기준 잡기 → 최소한의 강제 업데이트로 복구” 순서입니다.

1단계: PR의 base branch부터 확인한다

PR 화면에서 base branch가 의도한 대상인지 확인하세요.

  • 의도: feature/my-workdevelop에 합치려는 PR
  • 실제: main 기준 PR로 열려 있음

이 경우 main에 없는 커밋들이 한꺼번에 보이면서 “중복”처럼 느껴질 수 있습니다. 먼저 PR의 base를 올바르게 바꾸고, 커밋 목록/변경 파일이 정상인지 다시 확인합니다.

2단계: 로컬에서 merge-base로 “비교 기준”을 눈으로 확인한다

PR이 왜 커졌는지 보려면, 내 브랜치와 base 사이의 공통 조상을 확인하면 됩니다.

# 최신 상태로 맞추기
git fetch origin

# 내 브랜치와 base 브랜치의 공통 조상 확인
git merge-base HEAD origin/develop

# 공통 조상부터 내 브랜치까지 커밋 목록 확인
git log --oneline $(git merge-base HEAD origin/develop)..HEAD
  • 여기서 예상보다 오래된 커밋부터 보이면, 비교 기준이 꼬였거나 base가 잘못됐을 가능성이 큽니다.

3단계: “중복 커밋”이 진짜 중복인지 패치로 판별한다

커밋 SHA는 달라도 내용이 같을 수 있습니다. 이때는 패치 기준으로 동일 커밋인지 확인하는 게 가장 정확합니다.

# 패치 ID로 동일 변경인지 확인 (SHA가 달라도 동일 패치면 같은 변경)
git show <commit-sha> | git patch-id --stable

<commit-sha>처럼 부등호가 들어가는 표기는 MDX에서 오해될 수 있으니, 실제 사용 시에는 abc1234 같은 커밋 SHA로 바꿔서 실행하세요.

또는 브랜치 간에 “동일 변경이 이미 base에 들어갔는지”를 빠르게 보려면:

# 특정 커밋이 다른 브랜치에 이미 포함됐는지 유사도 기반으로 확인
git cherry -v origin/develop HEAD
  • + 는 develop에 없는 커밋
  • - 는 develop에 이미 있는(패치가 같은) 커밋

이 결과가 - 가 많은데 PR에서는 커밋이 잔뜩 보인다면, “내용은 이미 들어갔는데 rebase로 SHA가 바뀌어 PR이 헷갈리는” 전형적인 케이스입니다.

4단계: 올바른 rebase를 다시 수행한다 (가장 흔한 정답)

대부분의 팀에서는 feature 브랜치를 최신 develop 위로 재정렬하고 PR을 유지하면 해결됩니다.

git checkout feature/my-work
git fetch origin

# develop 최신 커밋 위로 내 커밋을 다시 얹기
git rebase origin/develop

충돌이 나면 해결 후:

git add -A
git rebase --continue

만약 특정 커밋을 “이미 upstream에 들어간 동일 변경”이라서 제거해야 한다면, 인터랙티브 rebase로 드롭합니다.

# 최근 10개 커밋을 편집
git rebase -i HEAD~10

편집 화면에서 중복된 커밋을 drop 하거나, 여러 커밋을 squash로 합쳐 PR을 깔끔하게 만들 수 있습니다.

5단계: PR 브랜치 푸시는 --force-with-lease로만 한다

rebase는 히스토리를 바꾸기 때문에 원격 브랜치 업데이트가 필요합니다. 이때 무조건 --force를 쓰면 동료의 푸시를 덮어쓸 수 있어 위험합니다.

git push --force-with-lease origin feature/my-work
  • --force-with-lease는 “내가 마지막으로 본 원격 상태에서 변한 게 없을 때만 강제 푸시”를 허용합니다.
  • 팀 작업에서 rebase 후 푸시는 사실상 이 옵션이 표준에 가깝습니다.

6단계: 그래도 PR이 계속 이상하면 ‘새 브랜치로 PR 재생성’이 가장 빠르다

도구(UI) 캐시나 복잡한 히스토리 꼬임 때문에 PR이 계속 이상하게 보일 때가 있습니다. 이때는 시간을 더 쓰지 말고, 깨끗한 브랜치로 새 PR을 만드는 게 실전적으로 가장 빠릅니다.

# 현재 상태를 새 브랜치로 분기
git checkout -b feature/my-work-clean

# 새 브랜치를 푸시
git push -u origin feature/my-work-clean

이후 새 PR을 열고, 기존 PR은 닫되 링크로 서로 연결해두면 리뷰 히스토리 추적도 가능합니다.

자주 나오는 케이스별 처방 요약

케이스 A: base branch가 잘못됨

  • 증상: 커밋이 대량으로 보임, 변경 파일이 뜬금없이 많음
  • 처방: PR base를 올바르게 수정 후 재확인

케이스 B: rebase 후 강제 푸시를 안 함

  • 증상: 로컬은 정리됐는데 PR은 그대로임
  • 처방: git push --force-with-lease

케이스 C: 이미 머지된 커밋을 또 체리픽/리베이스로 가져옴

  • 증상: 내용은 같은데 커밋이 새로 생김
  • 처방: git cherry -v로 확인 후 git rebase -i에서 drop

케이스 D: merge commit과 rebase가 섞여 merge-base가 꼬임

  • 증상: diff가 폭증, 커밋 중복처럼 보임
  • 처방: feature를 최신 base 위로 git rebase origin/develop 재수행, 필요 시 새 브랜치 PR

팀에서 재발을 줄이는 운영 팁

  1. 브랜치 전략을 문서로 고정

    • 예: feature는 항상 develop에서 분기, PR base는 develop, 머지는 squash
  2. rebase 허용 구간을 정한다

    • “리뷰 시작 전까지는 자유롭게 rebase”
    • “리뷰 시작 후에는 커밋 추가만 하고, 히스토리 변경은 합의 후” 같은 규칙이 있으면 PR 혼란이 확 줄어듭니다.
  3. PR 템플릿에 체크 항목 추가

    • base branch 확인
    • rebase 후에는 --force-with-lease로 푸시했는지

운영에서 중요한 건 기술 자체보다 “실수했을 때 안전장치가 있느냐”입니다. 장애 대응 체크리스트를 만들어두는 방식은 Git 운영에도 그대로 적용됩니다. 비슷한 체크리스트 접근이 궁금하면 Assistants API v2 run이 queued나 in_progress에 멈출 때 실전 디버깅 체크리스트처럼 문제를 단계적으로 쪼개는 글도 참고할 만합니다.

마무리: 결론은 ‘비교 기준’과 ‘히스토리 재작성’이다

rebase 후 PR 커밋 중복은 대부분 아래 두 가지 중 하나로 귀결됩니다.

  • PR의 base branch/merge-base(비교 기준) 가 예상과 다르다
  • rebase로 커밋 SHA가 바뀌었는데, PR 브랜치를 적절히 강제 업데이트하지 않았거나, 이미 포함된 변경을 또 얹었다

이 글의 6단계를 그대로 따라가면, 원인을 과잉 추측하지 않고도 “지금 PR이 왜 이렇게 보이는지”를 명확히 확인하고, 안전하게 정상 상태로 되돌릴 수 있습니다.