Git & GitHub

Git 협업 플로우 — PR 올리기 전 필수 순서 정리

승주우에요 2026. 4. 9. 07:17

협업 시 브랜치 동기화, merge, rebase 어떤 순서로 해야할지 헷갈려 정리해보았다!

1. 상황 설정

  • 공용 브랜치는 develop
  • 나는 feature/login 브랜치에서 작업 중
  • 작업하는 동안 팀원이 feature/payment를 develop에 먼저 머지한 상태
develop:        A --- B --- C --- D (팀원 커밋)
                      \
feature/login:         X --- Y --- Z (내 커밋)

이 상태에서 PR을 올리면 develop과 feature/login 사이에 격차가 생겨 컨플릿이 발생할 수 있습니다.


2. 전체 흐름 한눈에 보기

① local develop pull
      ↓
② feature rebase develop
      ↓
③ feature push --force-with-lease
      ↓
④ GitHub PR 생성
      ↓
⑤ 팀원 리뷰 → merge

3. 단계별 시나리오

Step 1 — local develop pull

먼저 로컬 develop을 원격 최신 상태로 맞춥니다.

git checkout develop
git pull origin develop
develop:  A --- B --- C --- D  ← 팀원 커밋(D)까지 반영됨

develop 브랜치는 직접 커밋하지 않으므로 단순히 pull로 당겨오면 충분합니다.


Step 2 — feature rebase develop

feature 브랜치로 돌아와 develop 위로 커밋을 이동시킵니다.

git checkout feature/login
git rebase develop
# rebase 전
develop:        A --- B --- C --- D
                      \
feature/login:         X --- Y --- Z

# rebase 후
develop:        A --- B --- C --- D
                                   \
feature/login:                      X' --- Y' --- Z'

내 커밋(X, Y, Z)이 develop의 최신 커밋(D) 위로 올라갑니다.
이 시점에 컨플릿이 있다면 바로 해결할 수 있습니다.

이때, X,Y,Z는 완전 새로운 커밋이 되버린다!


Step 3 — feature push --force-with-lease

rebase를 하면 커밋 해시가 바뀌기 때문에 일반 push가 거절됩니다. --force-with-lease 옵션으로 안전하게 강제 푸시합니다.

git push origin feature/login --force-with-lease

이때 원격 커밋 이력은 어떻게 바뀌나?

force push는 원격 브랜치를 로컬 기준으로 통째로 교체합니다.

# force push 전 원격 feature/login (이전에 X, Y까지 push한 상태)
X --- Y --- Z

# force push 후 원격 feature/login
A --- B --- C --- D --- X' --- Y' --- Z'  ← 덮어씌워짐

X, Y, Z는 사라지고 rebase된 X', Y', Z'로 교체됩니다.
X'는 X와 변경 내용(diff)은 동일하지만 커밋 해시가 다른 새 커밋입니다. rebase는 커밋을 "옮기는" 것처럼 보이지만 실제로는 새로 만드는 동작이기 때문입니다.

주의 — feature 브랜치는 나만 쓰는 브랜치이기 때문에 force push가 허용됩니다. develop, main 같은 공유 브랜치에는 절대 force push하면 안 됨!

--force-with-lease는 내가 모르는 사이 팀원이 같은 브랜치에 push한 경우 강제 푸시를 막아줌. --force보다 안전한 옵션입니다.


Step 4 — GitHub PR 생성

GitHub에서 feature/login → develop 으로 PR을 생성합니다.

이미 rebase로 develop과 동기화된 상태이므로 컨플릿 없이 머지 가능한 상태가 됩니다.


Step 5 — 팀원 리뷰 후 merge

팀원의 코드 리뷰 후 GitHub에서 머지합니다.

develop:  A --- B --- C --- D --- X' --- Y' --- Z'

feature/login의 커밋들이 develop 히스토리에 깔끔하게 이어집니다.


4. rebase 중 컨플릿이 발생한다면?

rebase 도중 컨플릿이 발생하면 Git이 해당 커밋에서 멈춥니다.

# 컨플릿 발생 시
CONFLICT (content): Merge conflict in login.py
error: could not apply X... feat: 로그인 UI 추가

해결 순서는 다음과 같습니다.

# 1. 컨플릿 파일 직접 수정
#    (<<<<<<< HEAD 마커 제거 후 최종 코드로 정리)

# 2. 스테이징
git add login.py

# 3. rebase 계속 진행
git rebase --continue

컨플릿을 포기하고 rebase 이전 상태로 되돌리려면 git rebase --abort를 사용합니다.


5. 정리

단계 명령어 목적

develop 최신화 git pull origin develop 원격 변경 사항 로컬에 반영
feature 동기화 git rebase develop 내 커밋을 develop 위로 이동
원격 feature 업데이트 git push --force-with-lease rebase 후 강제 푸시
PR 생성 GitHub UI 코드 리뷰 요청
머지 GitHub UI develop에 반영

PR을 올리기 전에 항상 develop을 pull → feature를 rebase 하는 습관을 들이면 컨플릿 없이 깔끔한 히스토리를 유지할 수 있다!