-
깃은 줄바꿈시 해당 라인에 /n 가 포함된다.깃 2024. 10. 27. 16:09
1.개요
같은 파일을 수정하더라도 서로 다른 라인만 수정한다면 Git Merge 시 충돌이 발생하지 않을 것이라는 일반적인 개발 관행과 기대를 바탕으로 작업을 진행했으나, 예상치 못한 충돌이 발생한 사례와 그 기술적 원인을 분석한 내용입니다.
2.시나리오
Main 브랜치, Sonata 브랜치(Main 의 Peature 브랜치), Grandeur 브랜치(Main 의 Peature 브랜치)가 존재하고 Sonata.js파일이 존재함
const engineStart = () => { console.log('부르릉'); };A 개발자가 Sonata 브랜치로 Sonata.js 파일의 2번째줄을 수정 후 커밋/푸시
const engineStart = () => { console.log('부르릉~~~~~!'); };B 개발자가 실수로 Granduer 브랜치로 Sonata.js 파일의 2번째줄을 동시에 수정 후 커밋/푸시
const engineStart = () => { console.log('휴유융'); };B 개발자가 실수를 인지하고 Granduer 브랜치로 2번째줄 수정내용을 원복했다. 그런데 실수로 엔터를 쳐서 줄바꿈이 일어난 상태로 커밋/푸시
const engineStart = () => { console.log('부르릉'); };Main 브랜치에 Grandeur 브랜치 머지 이후 Main 브랜치에 Sonata 브랜치 merge 시 2번째 라인 충돌 발생


3.충돌 원인 파악
Sonata.js 파일을 보면 2번째 라인은 Sonata, Granduer 브랜치가 서로 다르게 수정한 부분이 없다. 그냥 console.log('부르릉~~~~~!'); 상태로 merge 될 것이라 생각이 든다. 3번째 라인도 마찬가지다. 근데 왜 충돌이 발생하는걸까?
그건 바로 "줄바꿈 문자의 숨겨진 변경" 때문이다. 사용자가 Enter 키를 눌러 줄바꿈을 유발했을 때, Git은 파일에 보이지 않는 제어 문자를 삽입하게된다.
- 실제 삽입되는 제어 문자: 운영체제에 따라 \n (Line Feed, LF) 또는 \r\n (Carriage Return + Line Feed, CRLF)
- 브랜치의 수정 내역: Granduer 브랜치에서 수정한 2번째 라인의 내용 끝에 이 줄바꿈 문자가 추가됩니다.
- Git의 커밋 메시지나 일반적인 Diff 도구에서는 이 문자가 시각적으로 명확하게 드러나지 않고, 단지 다음 라인이 시작되는 것처럼 보입니다.
위 현상 때문에 깃 내부적으로 Granduer 브랜치에서 2번째 라인을 console.log('부르릉');\n 로 수정한것이고
Sonata 브랜치에서 2번째 라인을 console.log('이유융'); 로 수정한거라 충돌이 발생된것
4.충돌의 교훈
Git의 관점에서 줄바꿈은 다른 개발자의 작업을 덮어쓰거나 충돌을 유발할 수 있는 엄연한 수정입니다.
개발자는 코드를 원복할 때나 포맷팅할 때 불필요한 공백이나 줄바꿈이 삽입되지 않도록 각별히 주의해야 한다.
5.제어 문자 해결방안 참고문서
아래 공식 문서에 위 줄바꿈 제어 문자 해결방안 및 제어 문자에 대한 내용을 확인할 수 있다.
https://docs.github.com/ko/get-started/git-basics/configuring-git-to-handle-line-endings
줄 끝을 처리하도록 Git 구성 - GitHub 문서
diff에서의 문제를 방지하기 위해 줄 끝을 제대로 처리하도록 Git을 구성할 수 있습니다.
docs.github.com