.gitattributes를 통한 submodule 머지 충돌 해결

ILJUN YUN·2025년 8월 16일
post-thumbnail

1. 들어가며

최근 상위 저장소의 prod 브랜치와 dev 브랜치가 각각 다른 submodule 커밋을 가리키고 있었는데, 머지하는 순간 submodule 충돌이 발생했습니다. 단순히 git status만 보면 “서브모듈 충돌”이라는 메시지로 끝이라 처음엔 왜 그런지 이해하기 어려웠습니다.

2. submodule이란?

submodule은 Git 저장소 안에 또 다른 Git 저장소를 넣는 기능입니다. 일반 파일 처럼 복사해오는 것이 아니라 특정 커밋 해시를 가리키는 포인터를 저장합니다. 그렇기 때문에 공통 모듈을 여러 프로젝트에서 동일하게 재사용할 수 있습니다.

하지만 브랜치별로 submodule이 다른 커밋을 가리킬 때, 머지를 하면 충돌이 발생할 수 있습니다. 예를 들어 상위 저장소의 prod브랜치는 submodule의 prod브랜치를 가리키고 상위 저장소의 dev브랜치는 submodule의 dev브랜치를 가리키고 있는데 각각 다른 커밋을 갖고 있는 두 브랜치 사이에 머지를 하려고 하면 충돌이 발생합니다.

3. .gitattributes로 해결

.gitattributes는 Git이 파일을 다룰 방식을 정의하는 역할을 합니다.
특히 submodule 충돌이 날 때 유용합니다. 예를 들어,

common_module merge=ours

위와 같이 설정하면, common_module submodule에서 머지 충돌이 발생했을 때 현재 브랜치의 버전(ours)을 자동으로 선택하게 됩니다.

또 다른 예시는 diff 설정입니다.

*.md diff=markdown
*.png binary

마크다운 파일은 markdown diff를 사용하라는 뜻이고, png 파일은 binary이니까 diff 하지 말라는 뜻입니다. markdown diff를 사용하게 되면 마크다운 문서를 단순히 줄 단위로만 보는 게 아니라, 마크다운 전용 diff드라이버를 적용할 수 있습니다. 제목, 리스트, 링크 등 마크다운 문법 요소를 인식해서 더 의미 있는 비교를 제공합니다.

다시 문제 상황으로 돌아와서 브랜치 A/B가 서로 다른 submodule 커밋을 가리켜서 충돌이 날 때, .gitattributes로 정책 반영해주면 됩니다. 브랜치 A/B에 각각 .gitattributes파일을 수정 및 커밋시켜주고 머지를 다시 시도하면 정책이 반영되어 머지를 하더라도 각각의 브랜치가 가리키는 submodule로 정리됩니다.

4. .gitignore으로는 해결할 수 없을까?

.gitignore은 말 그대로 Git이 추적하지 않도록 설정하는 파일입니다. 예를 들어,

common_module

위와 같이 .gitignore파일을 작성했다면 “아예 추적하지 않는다”는 의미라 Git이 submodule 버전을 관리하지 않습니다. 충돌은 피할 수 있지만, 팀원마다 submodule 버전이 달라져 빌드나 테스트가 엉킬 수 있습니다. 반면 .gitattributes는 추적은 하되, 충돌 시 어떻게 해석할지 정의하기 때문에 일관성을 유지하면서 충돌을 자동으로 해결할 수 있습니다.

5. 마무리

정리하면,

  • submodule은 공통 모듈을 일괄 관리할 수 있어 유용하지만,
  • 브랜치마다 다른 커밋을 가리킬 때는 머지 충돌을 일으키기 쉽습니다.
  • .gitattributes를 활용해 충돌 처리 정책을 정의하면 이러한 문제를 근본적으로 해결할 수 있습니다.

사실 이 문제는 꽤 오래 겪고 있었지만, 그동안은 당장 눈앞의 충돌만 해결하느라 근본적인 방법을 찾지 못했습니다. 이번 경험을 통해 새로운 문제 상황이 생겼을 때는 먼저 원인과 근본 해결 방법을 확인하고 빠르게 반영하는 습관이 중요하다는 걸 다시 한번 깨닫게 되었습니다.

profile
한정된 자원으로 더 많은 가치를 제공하려고 노력하는 백엔드 엔지니어입니다.

0개의 댓글