Git Divergent Branch 해결과 --ours/--theirs가 merge·rebase에서 뒤바뀌는 이유

git pull이 divergent branches 에러로 막혔을 때 merge·rebase 전략을 고르는 법과, --ours/--theirs 의미가 merge와 rebase에서 반대가 되는 원리

2026-08-12 · 최초 발행 2026-04-17

fatal: Need to specify how to reconcile divergent branches라는 에러를 한 번쯤 마주친다. Git 2.27부터 divergent branch를 pull할 때 merge와 rebase 중 어떤 전략을 쓸지 명시적으로 선택하도록 정책이 바뀌었기 때문이다. 여기에 충돌 해결 시 등장하는 --ours--theirs 옵션은 merge와 rebase에서 의미가 뒤바뀌어 혼란을 더한다.

Divergent Branch란

로컬 브랜치와 원격 브랜치가 각각 독립적인 커밋을 갖고 있어 히스토리가 갈라진 상태를 말한다.

mainorigin/masterBaseR1 (remote)R2 (remote)L1 (local)L2 (local)L3 (local)

발생 조건은 대체로 세 가지다.

  • 로컬에서 커밋 후 push하지 않은 상태에서 다른 개발자가 원격에 push
  • 서로 다른 머신에서 같은 브랜치에 작업
  • git commit --amend로 이미 push된 커밋을 수정한 경우

이때 Git이 보여주는 에러 메시지는 세 가지 선택지를 함께 안내한다.

hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only

Pull 전략

Merge 전략 (pull.rebase false)

두 갈래의 히스토리를 병합 커밋(merge commit)으로 합친다.

git pull --no-rebase
# 또는 기본값 설정
git config pull.rebase false
BaseL1L2L3Merge CommitR1R2
장점 단점
히스토리 보존 merge commit으로 히스토리 복잡
충돌 해결이 한 번 비선형 그래프
안전하고 간단 git log가 지저분해짐

Rebase 전략 (pull.rebase true)

로컬 커밋을 원격 최신 커밋 위에 다시 쌓는다(replay). 히스토리가 일직선으로 유지된다.

git pull --rebase
# 또는 기본값 설정
git config pull.rebase true
BaseR1R2L1'L2'L3'
장점 단점
깔끔한 선형 히스토리 커밋마다 충돌 가능
git log가 읽기 쉬움 커밋 해시 변경
merge commit 없음 공유 브랜치에서 위험

Fast-forward Only (pull.ff only)

divergent 상태에서는 pull 자체를 거부한다.

git config pull.ff only

divergent가 아닌 경우(원격만 앞서 있는 경우)에만 pull이 성공한다. 안전하지만 divergent 상태가 되면 매번 수동 개입이 필요하다.

전략 선택 가이드

YesNoYesNogit pull 실패혼자 작업하는브랜치인가?rebase 권장히스토리깔끔함 중요?rebase (주의 필요)merge 권장git pull --rebasegit pull --no-rebase

Ours와 Theirs의 의미

Git 충돌 해결에서 가장 헷갈리는 부분이다. merge와 rebase에서 ours/theirs의 의미가 뒤바뀐다.

Merge 시 Ours/Theirs

현재 체크아웃된 브랜치(HEAD)가 ours, 병합 대상 브랜치가 theirs다.

theirs (병합 대상)ours (HEAD = 현재 브랜치)로컬 커밋 1로컬 커밋 2원격 커밋 1원격 커밋 2Merge
# merge 중 충돌 시 — 로컬(현재 브랜치) 버전 선택
git checkout --ours <file>

# merge 중 충돌 시 — 원격(병합 대상) 버전 선택
git checkout --theirs <file>

Rebase 시 Ours/Theirs (주의: 반대!)

Rebase는 내부적으로 대상 브랜치에 체크아웃한 뒤 로컬 커밋을 하나씩 replay한다. 따라서 ours = 리베이스 대상(원격), theirs = 내 커밋이 된다.

rebase 내부 동작(1) origin/master로 체크아웃(= ours)(2) 로컬 커밋을 하나씩 적용 (=theirs)(3) 충돌 ours = origin,theirs = 커밋
# rebase 중 충돌 시 — 원격(대상 브랜치) 버전 유지
git checkout --ours <file>

# rebase 중 충돌 시 — 내 로컬 변경사항 유지
git checkout --theirs <file>

요약 테이블

작업 --ours --theirs
merge 현재 브랜치 (내 코드) 병합 대상 (원격/상대 코드)
rebase 대상 브랜치 (원격 코드) 내 커밋 (내 코드)

핵심은 이 한 줄로 기억하면 된다: 내 코드를 유지하고 싶다면 merge에서는 --ours, rebase에서는 --theirs.

Merge 전략 옵션 상세

파일 단위 해결: git checkout

충돌 발생 후 특정 파일 전체를 한쪽 버전으로 교체한다.

# 충돌 발생
git merge feature-branch

# 특정 파일을 현재 브랜치(ours) 버전으로
git checkout --ours config.json
git add config.json

# 특정 파일을 상대 브랜치(theirs) 버전으로
git checkout --theirs package-lock.json
git add package-lock.json

자동 해결: -X 전략 옵션

비충돌 부분은 정상 merge하고, 충돌 부분만 지정한 쪽을 선택한다.

# 충돌 시 현재 브랜치 우선
git merge -Xours feature-branch

# 충돌 시 상대 브랜치 우선
git merge -Xtheirs feature-branch

완전 무시: -s ours 전략

상대 브랜치의 모든 변경사항을 무시하고 merge 기록만 남긴다. 매우 위험하므로 신중하게 사용해야 한다.

# feature-branch의 모든 변경을 무시하고 merge 기록만 생성
git merge -s ours feature-branch

옵션 비교

Yes충돌 부분만상대 전체 무시No파일 단위라인 단위충돌 해결 방법 선택자동 해결원하는가?충돌 부분만?전체?-Xours / -Xtheirs-s ours (위험!)파일 단위?라인 단위?checkout --ours/--theirs에디터에서 수동 편집
명령 범위 동작 위험도
checkout --ours/--theirs 파일 단위 해당 파일만 교체 낮음
merge -Xours/-Xtheirs 충돌 라인 충돌 부분만 자동 선택, 나머지 정상 merge 중간
merge -s ours 전체 상대 브랜치 변경 전부 무시 높음

실전 시나리오별 대응

시나리오 1: lock 파일 충돌

package-lock.json, yarn.lock 등 자동 생성 파일은 수동 merge가 무의미하다.

# merge 후 lock 파일 충돌 시
git checkout --theirs package-lock.json  # 원격 버전 수용
git add package-lock.json
npm install  # 로컬 의존성 재생성
git add package-lock.json
git commit

시나리오 2: 설정 파일은 로컬 유지

로컬 환경에 맞춘 설정 파일은 항상 로컬 버전을 유지한다.

git checkout --ours .env.local
git add .env.local

시나리오 3: Rebase 중 반복 충돌

rebase는 커밋마다 충돌이 발생할 수 있다. 너무 많으면 abort 후 merge로 전환한다.

# rebase 포기
git rebase --abort

# merge로 전환
git merge origin/master

시나리오 4: Untracked 파일과 Rebase 충돌

로컬에 untracked 파일이 있는데 rebase 대상 커밋이 같은 파일을 생성하는 경우다.

error: The following untracked working tree files would be overwritten by merge
# 방법 1: stash로 임시 보관
git stash --include-untracked
git rebase --continue
git stash pop

# 방법 2: rebase 포기 → merge
git rebase --abort
git merge origin/master

글로벌 기본값 설정 권장

매번 옵션을 지정하지 않으려면 글로벌 설정을 해두는 것이 좋다.

# 개인 프로젝트 — rebase 기본값 (깔끔한 히스토리)
git config --global pull.rebase true

# 팀 프로젝트 — merge 기본값 (안전)
git config --global pull.rebase false

# mergetool을 Neovim으로 설정
git config --global merge.tool nvimdiff
git config --global mergetool.nvimdiff.layout "LOCAL,MERGED,REMOTE"

마무리

divergent branch 에러는 로컬과 원격의 히스토리가 갈라졌을 때 발생하며, merge(병합 커밋 생성)와 rebase(히스토리 재작성) 중 선택해서 해결한다. 충돌 해결 시 --ours--theirs는 merge에서는 직관적이지만 rebase에서는 의미가 반대로 뒤집히므로, 지금 작업이 merge인지 rebase인지부터 확인하는 습관이 필요하다.

Git머지리베이스충돌 해결Divergent Branch