프로덕션 서버에서 “Git Divergent Branches” 오류 해결하기 (실제 DevOps 디버깅 워크스루)
요약
프로덕션 서버 배포 중 발생하는 Git의 'Divergent Branches' 오류 원인을 분석하고 해결책을 제시합니다. 서버 로컬과 원격 저장소의 히스토리가 불일치할 때 발생하는 문제를 진단하고, 안전한 배포를 위한 Git 관리 방법을 설명합니다.
핵심 포인트
- Git Divergent Branches 오류는 로컬과 원격의 히스토리가 갈라졌을 때 발생함
- 서버에서 직접 커밋을 수행하거나 비선형적 히스토리가 생길 때 주로 발생
- 프로덕션 환경에서는 git pull 대신 git reset --hard를 권장
- 결정론적 리셋을 통해 서버 상태를 원격 저장소와 항상 일치시켜야 함
Node.js 또는 Docker 기반 애플리케이션을 배포할 때 직면할 수 있는 가장 혼란스러운 오류 중 하나는 다음과 같습니다:
fatal: Need to specify how to reconcile divergent branches
언뜻 보기에는 Git 버그처럼 보입니다. 하지만 실제로는 Git이 히스토리가 덮어씌워지는 것을 방지하기 위해 마땅히 해야 할 일을 수행하고 있는 것입니다.
이 글에서는 Git 브랜치가 갈라져(divergent) 배포가 실패한 실제 프로덕션 사고 사례를 분석하고, 이를 어떻게 진단했는지, 그리고 올바른 DevOps 해결책은 무엇인지 설명하겠습니다.
문제 (The Problem)
간단한 배포 스크립트가 실행되고 있었습니다:
git pull
docker compose down --remove-orphans
docker compose up --build -d
하지만 다음과 같은 오류와 함께 실패했습니다:
fatal: Need to specify how to reconcile divergent branches
이로 인해 배포가 완전히 중단되었습니다.
Git이 우리에게 말하고 있는 것 (What Git Was Telling Us)
문제를 이해하기 위해 다음 명령어를 실행했습니다:
git rev-list --left-right --count HEAD...origin/main
출력 결과:
1 16
이는 다음을 의미합니다:
- 서버 로컬에 1개의 커밋(commit)이 존재함
- GitHub에 16개의 커밋(commit)이 존재함
즉, 브랜치가 서로 갈라진(diverged) 상태였습니다.
이 현상이 발생하는 이유 (중요) (Why This Happens (Important))
이 문제는 보통 다음과 같은 상황에서 발생합니다:
- 누군가가 서버에서 직접
git commit을 실행했을 때 - 이전 배포에서 머지 커밋(merge commits)을 포함한
git pull을 사용했을 때 - 로컬과 원격(remote) 사이의 히스토리가 더 이상 선형적(linear)이지 않을 때
Git은 사용자가 다음 중 무엇을 원하는지 추측하기를 거부합니다:
- 머지 (Merge)
- 리베이스 (Rebase)
- 또는 변경 사항 거부 (Reject changes)
그래서 오류를 발생시키는 것입니다.
심층 진단 (Deep Diagnosis)
커밋(commit)을 조사했습니다:
git log --oneline origin/main..HEAD
결과:
6d9046b Merge pull request #222
그 다음:
git log --oneline HEAD..origin/main
명령어는 GitHub의 여러 새로운 PR 머지(merge)를 보여주었습니다.
결론:
- 서버가 GitHub보다 뒤처져 있었음
- “로컬 커밋(local commit)”은 이미 리포지토리(repo) 히스토리의 일부였음
- 서버에는 실제 프로덕션 변경 사항이 존재하지 않았음
실제 해결책 (프로덕션 안전 방식) (The Real Fix (Production Safe))
배포 서버의 경우, 절대로 git pull에 의존해서는 안 됩니다.
대신, 결정론적인 리셋(deterministic reset)을 사용하십시오:
git fetch origin
git reset --hard origin/main
그 다음 다시 배포하십시오:
docker compose down --remove-orphans
docker compose up --build -d
작동 원리 (Why This Works)
이 방식은 다음을 보장합니다:
- 서버가 항상 GitHub와 정확히 일치함
- 프로덕션 (Production) 환경에서 병합 충돌 (Merge conflicts) 발생 방지
- 실수로 생성된 로컬 커밋 (Local commits)이 남지 않음
- 완전히 재현 가능한 배포 (Reproducible deployments)
이는 프로덕션 환경에서 사용되는 표준 CI/CD 패턴입니다.
잘못된 접근 방식 (The Broken Approach)
서버에서는 다음 방식을 피하십시오:
git pull
이유는 무엇일까요?
이 방식은 다음과 같은 문제를 일으킬 수 있기 때문입니다:
- 병합 충돌 (Merge conflicts)을 유발할 수 있음
- 로컬 히스토리 (Local history) 상태에 의존함
- 예기치 않게 배포를 망가뜨릴 수 있음
권장되는 배포 스크립트 (Best Practice Deployment Script)
cd opt/yourprojectdirectory
echo "Fetching latest code..."
...
핵심 교훈 (Key Lesson)
프로덕션 서버는 "코드를 병합(Merge)"해서는 안 됩니다.
서버는 **GitHub를 정확히 미러링(Mirror)**해야 합니다.
결론 (Conclusion)
이 문제는 처음에는 무섭게 보일 수 있지만, 실제로는 단순한 Git 히스토리 불일치 문제입니다.
다음 개념들을 이해하고 나면:
HEADorigin/main- divergence (발산/차이)
...30초 이내에 문제를 해결할 수 있습니다.
DevOps를 수행하거나 배포를 관리하고 있다면, 이는 심야 시간에 프로덕션 서버가 패닉에 빠지는 상황을 막아줄 핵심 기초 지식 중 하나입니다.
이 분석이 도움이 되었다면, 앞으로도 이와 같은 실무 DevOps 디버깅 사례를 더 많이 공유하겠습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기