DaleSchool

충돌 해결

입문25분

학습 목표

  • 충돌이 발생하는 상황을 두 가지 이상 설명할 수 있다
  • 충돌 마커를 읽고 직접 해결할 수 있다
  • 충돌 해결 후 머지를 완료할 수 있다
  • 충돌을 예방하는 습관을 기를 수 있다

동작하는 코드

예제 1: 충돌 시나리오 만들기

git init
echo "프로젝트 v1.0" > version.txt
git add version.txt
git commit -m "feat: 초기 버전 파일 추가"

feature 브랜치에서 수정:

git checkout -b feature-update
echo "프로젝트 v2.0 (feature)" > version.txt
git add version.txt
git commit -m "feat: version을 2.0으로 업데이트"

main에서도 같은 파일 수정:

git checkout main
echo "프로젝트 v1.1 (main)" > version.txt
git add version.txt
git commit -m "fix: 버전 1.1로 패치"

이제 merge를 시도합니다:

git merge feature-update

출력:

CONFLICT (content): Merge conflict in version.txt
Automatic merge failed; fix conflicts and then commit the result.

예제 2: 충돌 파일 확인

cat version.txt

출력:

<<<<<<< HEAD
프로젝트 v1.1 (main)
=======
프로젝트 v2.0 (feature)
>>>>>>> feature-update

충돌 마커 읽기:

<<<<<<< HEAD          ← 현재 브랜치(main) 내용 시작
프로젝트 v1.1 (main)
=======               ← 구분선
프로젝트 v2.0 (feature)
>>>>>>> feature-update ← 병합할 브랜치 내용 끝

예제 3: 충돌 해결

편집기로 충돌 파일을 열어 원하는 내용으로 수정합니다:

# 마커를 지우고 원하는 내용으로 수정
echo "프로젝트 v2.0" > version.txt

# 해결 표시
git add version.txt

# 머지 완료
git commit -m "merge: feature-update 병합, 버전 2.0으로 통합"

직접 수정하기

시나리오 2: 여러 섹션 충돌

실제 프로젝트에서는 파일 여러 곳에서 충돌이 발생합니다:

git init
cat > README.md << 'EOF'
# 프로젝트
## 소개
여기에 소개 글

## 설치
여기에 설치 방법
EOF
git add README.md
git commit -m "docs: README 추가"

# feature에서 소개와 설치 모두 수정
git checkout -b feature-docs
cat > README.md << 'EOF'
# 멋진 프로젝트
## 소개
이 프로젝트는 정말 멋집니다.

## 설치
npm install을 실행하세요.
EOF
git add README.md
git commit -m "docs: README 내용 추가"

# main에서도 소개만 수정
git checkout main
cat > README.md << 'EOF'
# 프로젝트 v2
## 소개
이 프로젝트의 새 버전입니다.

## 설치
여기에 설치 방법
EOF
git add README.md
git commit -m "docs: 버전 정보 추가"

git merge feature-docs

충돌 파일:

<<<<<<< HEAD
# 프로젝트 v2
## 소개
이 프로젝트의 새 버전입니다.

## 설치
여기에 설치 방법
=======
# 멋진 프로젝트
## 소개
이 프로젝트는 정말 멋집니다.

## 설치
npm install을 실행하세요.
>>>>>>> feature-docs

두 내용을 합쳐서 해결:

cat > README.md << 'EOF'
# 멋진 프로젝트 v2
## 소개
이 프로젝트의 새 버전이며 정말 멋집니다.

## 설치
npm install을 실행하세요.
EOF

git add README.md
git commit

시나리오 3: 삭제 vs 수정 충돌

git init
echo "삭제될 예정인 파일" > old-file.txt
git add old-file.txt
git commit -m "add: 임시 파일"

git checkout -b cleanup
git rm old-file.txt
git commit -m "chore: 불필요한 파일 삭제"

git checkout main
echo "파일 수정" >> old-file.txt
git add old-file.txt
git commit -m "fix: 파일 수정"

git merge cleanup

출력:

CONFLICT (modify/delete): old-file.txt deleted in cleanup and modified in HEAD.

해결 방법:

git status
# "both modified" 표시

# 삭제를 선택
git rm old-file.txt
git commit -m "merge: 파일 삭제로 충돌 해결"

# 또는 파일 유지를 선택
git add old-file.txt
git commit -m "merge: 파일 수정 내용 유지"

"왜?" — 충돌은 언제 발생하나?

충돌이 발생하는 경우:

  • 두 브랜치가 같은 파일의 같은 줄을 다르게 수정
  • 한쪽은 파일 수정, 다른 쪽은 파일 삭제

Git이 자동으로 해결하는 경우:

  • 서로 다른 파일 수정
  • 같은 파일이지만 다른 줄 수정

충돌 해결 전략 3가지

<<<<<<< HEAD
현재 브랜치 내용
=======
병합 브랜치 내용
>>>>>>> feature-branch
  1. 현재 브랜치 유지: ===== 아래 삭제, HEAD 내용 유지
  2. 병합 브랜치 유지: ===== 위 삭제, feature 내용 유지
  3. 두 내용 합치기: 마커만 삭제, 두 내용 모두 유지하거나 조합

중요: 마커 라인(<<<, ===, >>>)을 반드시 모두 지워야 합니다. 마커가 남아있으면 파일이 깨집니다.

흔한 실수

실수 1: 충돌 마커를 파일에 남겨두기

# 충돌 해결 후 마커가 남아있으면 빌드/실행 오류
cat version.txt
# <<<<<<< HEAD        ← 마커가 남아있음!
# v1.0
# =======
# v2.0
# >>>>>>> feature

git diff로 마커가 없는지 확인하세요.

실수 2: git add 전에 commit

# 잘못된 순서
git commit   # 아직 충돌 해결 안 됨 → 에러

# 올바른 순서
# 1. 충돌 파일 편집
# 2. git add 파일명   (해결 표시)
# 3. git commit

실수 3: 어떤 브랜치 내용인지 잊기

# merge 중 현재 상태 확인
git status
# Both modified: version.txt

# HEAD가 어느 브랜치인지 확인
git branch
# * main  ← HEAD = main

HEAD는 현재 브랜치(main), feature-xxx는 병합할 브랜치입니다.

실수 4: 충돌 중간에 다른 작업

git merge feature-login   # 충돌 발생
# 아직 해결 안 함

git checkout develop      # 에러!
# error: Your local changes to the following files would be overwritten...

충돌은 완전히 해결하거나, git merge --abort로 취소한 후 다른 작업을 하세요.

심화 학습

VS Code에서 충돌 해결하기

VS Code는 충돌을 시각적으로 표시하고 버튼 한 번으로 해결할 수 있습니다:

  • Accept Current Change — HEAD(현재 브랜치) 내용 유지
  • Accept Incoming Change — 병합 브랜치 내용 유지
  • Accept Both Changes — 둘 다 유지 (순서대로)
  • Compare Changes — 차이 비교

충돌 파일은 Explorer에서 ! 아이콘으로 표시됩니다.

충돌 예방 습관

충돌을 완전히 없앨 수는 없지만 줄이는 방법:

  1. 자주 pull/merge: main의 변경 사항을 자주 feature에 반영

    git fetch origin
    git merge origin/main   # feature에서 실행
    
  2. 작은 단위로 PR: 큰 PR은 충돌 가능성 높음

  3. 파일 분리: 여러 사람이 같은 파일을 수정하지 않도록 구조화

  4. 커뮤니케이션: 같은 파일을 수정할 때 팀원과 조율

git mergetool 사용하기

복잡한 충돌은 머지 도구가 편합니다:

# VS Code를 머지 도구로 설정
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'

# 실행 (충돌 상태에서)
git mergetool

VS Code가 열리고 3-way merge(베이스, 현재, 대상)를 시각적으로 보여줍니다.

  1. 새 저장소에서 파일 하나를 만들고 커밋하세요.
  2. feature 브랜치와 main에서 같은 파일의 같은 줄을 다르게 수정하세요.
  3. merge를 시도해 충돌을 발생시키고 cat으로 충돌 마커를 확인하세요.
  4. 편집기로 충돌을 해결하고 git add + git commit으로 머지를 완료하세요.
  5. git log --oneline --graph로 머지 커밋을 확인하세요.

Q1. 충돌 해결 후 머지를 완료하려면 어떤 순서로 명령어를 실행해야 하나요?

  • A) git commitgit add 파일명
  • B) git add 파일명git commit
  • C) git merge --continue 만으로 충분
  • D) git pushgit commit