MMeshOps
바이브코딩을 위한 Git과 리눅스 기초
14예상 10입문

두려워할 필요 없는 충돌(Conflict) 해결법

브랜치를 병합할 때 발생하는 충돌(Conflict)의 원인을 이해하고, 당황하지 않고 수동으로 충돌을 해결하는 방법을 배웁니다.

우리는 이전 시간에 시냇물(`feature` 브랜치)을 강물(`main`)로 병합할 때 터미널이 스스로 코드를 부드럽게 섞어주는 "Fast-forward" 기적을 맛보았습니다. 하지만 Git이 아무리 똑똑해도 기계이기 때문에 스스로 판단을 내리지 못하고 인간의 결정을 요구하며 멈춰 설 때가 있습니다. 화면에는 무시무시한 에러 메시지가 쏟아지고, 파일 속에는 외계어 같은 특수기호가 가득 찹니다. 초보자들이 Git을 포기하게 만드는 가장 큰 장벽인 '병합 충돌(Merge Conflict)'의 발생 원인과, 이를 당황하지 않고 수동으로 깔끔하게 정리하는 방법을 익혀봅시다.

왜 충돌이 발생할까?

Git은 웬만한 코드 수정은 스스로 알아서 잘 합쳐줍니다. A라는 파일의 1번 줄을 고치고 다른 브랜치에서 10번 줄을 고쳤다면, 그냥 두 개를 알아서 한 파일에 합쳐버립니다. 문제는 "서로 다른 브랜치에서 완전히 '똑같은 파일'의 '똑같은 줄'을 각각 다르게 수정했을 때" 발생합니다.

예를 들어 웹사이트의 제목인 `<h1>` 태그를, `main` 브랜치에서는 "나의 멋진 서버"라고 수정했고, `feature` 브랜치에서는 바이브코딩 AI가 "나의 훌륭한 웹사이트"라고 수정했습니다. 이 상태에서 두 개를 병합(`git merge`)하려고 시도해 봅시다.

Git 입장에서는 대혼란이 옵니다. "둘 다 똑같은 10번째 줄을 고쳤네? 내가 '멋진'을 살려야 해, 아니면 '훌륭한'을 살려야 해? 내 마음대로 하나를 지웠다가는 주인이 화낼 텐데... 모르겠다, 주인님이 직접 눈으로 보고 하나를 골라달라고 에러를 띄우자!" 이것이 바로 충돌(Conflict)이 발생하는 유일한 원리입니다.

병합 충돌 발생 시 터미널의 비명

$ git merge feature-title
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

터미널에 무서운 대문자로 `CONFLICT`라는 단어가 뜨고, "자동 병합이 실패했으니 사람이 직접 충돌을 고친 다음에 커밋해라"라는 메시지가 나옵니다.

충돌 난 파일의 내부 모습

위와 같은 에러를 보고 겁을 먹고 터미널을 꺼버리면 영원히 충돌을 해결할 수 없습니다. 터미널은 끄지 말고, 에러 메시지가 콕 집어준 말썽꾸러기 파일(`index.html`)을 코드 에디터나 `cat` 명령어로 직접 열어봐야 합니다.

파일을 열어보면 Git이 인간에게 보내는 구원 요청 메시지가 아래와 같은 특이한 기호들로 코드 중간에 끼어들어가 있습니다.

<<<<<<< HEAD
  <h1>나의 멋진 서버</h1>
=======
  <h1>나의 훌륭한 웹사이트</h1>
>>>>>>> feature-title

이 기호들의 의미를 해독하는 것이 충돌 해결의 알파이자 오메가입니다.

  • `<<<<<<< HEAD` 부터 `=======` 까지: 현재 내가 머물고 있는 주인공 브랜치(`main`)에 적혀 있는 내용입니다.
  • `=======` 부터 `>>>>>>> feature-title` 까지: 내가 방금 흡수하려고 시도했던 대상 브랜치(`feature-title`)에 적혀 있는 내용입니다.
  • 가운데 `=======` 선을 기준으로 윗동네와 아랫동네가 멱살을 잡고 싸우고 있는 형국입니다.

재판관이 되어 싸움 말리기 (수동 해결 3단계)

이제 우리는 판사가 되어 이 두 줄의 코드 중 어떤 것을 살리고 어떤 것을 죽일지, 혹은 둘 다 살려서 적절히 짬뽕을 할지 최종 결론을 내려야 합니다.

충돌 해결 3단계 프로세스

  1. 11단계(파일 수정): 충돌 난 파일을 열어 흉측한 특수기호(<<<<, ====, >>>)를 백스페이스키로 모두 깨끗하게 지웁니다.
  2. 22단계(내용 결정): 두 버전 중 하나만 남기고 지우거나, 새로운 글자('나의 멋지고 훌륭한 서버')로 직접 텍스트를 수정하여 최종 완성본을 만듭니다.
  3. 33단계(해결 선언): 터미널로 돌아가서 수정한 파일을 git add . 한 뒤, git commit 명령어를 쳐서 충돌이 해결되었음을 시스템에 도장 찍어 선언합니다.

실제로 코드를 위 가이드에 따라 수정하고 나면 파일은 아래처럼 아주 깔끔하고 평범한 코드로 되돌아옵니다.

  <h1>나의 멋지고 훌륭한 웹사이트</h1>

수정을 마쳤으면 터미널에서 `git add index.html`을 치고, 이어서 `git commit`을 칩니다. 충돌이 발생한 상태에서 `add`를 하고 `commit`을 치면, Git은 눈치껏 "아, 주인님이 충돌을 해결하고 병합을 마무리 지으려고 하는구나"라고 알아듣고 자동으로 커밋 메시지를 완성해 줍니다.

충돌 발생 시 주의사항

권장

  • 당황하지 않고 git status를 쳐서 붉은색으로 'both modified'라고 적힌 파일들의 목록을 차분히 확인합니다.
  • 충돌 표식 기호(<<<<, ====, >>>>)는 반드시 백스페이스로 남김없이 싹 다 지워주어야 문법 에러가 나지 않습니다.
  • AI와 바이브코딩을 할 때는 똑같은 파일을 양쪽에서 건드리지 않도록, 한 번에 하나의 기능(한 명의 AI)하고만 작업해야 충돌을 줄일 수 있습니다.

주의

  • 무서워서 냅다 프로젝트 폴더를 지우고 처음부터 다시 설치하지 마세요. 충돌은 그저 코드 문자열의 싸움일 뿐입니다.

충돌은 실패나 에러가 아닙니다. 그저 코드가 덮어씌워져 날아가는 대참사를 막기 위해 리눅스와 Git이 우리에게 주는 '마지막 확인창'일 뿐입니다. 이 특수기호를 지우고 정리하는 감각만 익히면, 여러분은 Git의 가장 큰 산을 무사히 넘은 셈입니다.

개념 퀴즈

퀴즈 답을 맞춰야 학습 완료가 됩니다.

두 브랜치를 병합(merge)하는 중에 충돌(Conflict)이 발생하여 파일 내부를 열어보았습니다. 파일 중간에 껴있는 '<<<<<<< HEAD' 와 '=======' 사이의 코드가 의미하는 바는 무엇인가요?

3줄 요약

  1. 1병합 충돌(Conflict)은 두 개의 다른 브랜치에서 정확히 같은 파일의 같은 라인을 서로 다르게 수정했을 때, Git이 자동 판단을 포기하면서 발생합니다.
  2. 2충돌 난 파일에는 특수기호(<<<<<<<, =======, >>>>>>>)를 기준으로 두 버전의 코드가 위아래로 나뉘어 삽입됩니다.
  3. 3개발자는 특수기호를 모두 수동으로 지우고 최종 코드를 정리한 뒤, git add 와 git commit을 차례로 입력하여 충돌 상황을 종결해야 합니다.