Git - Encoding, Line Ending 오류 해결 방법
개발일지/CI & CD - Git, Jenkins

Git - Encoding, Line Ending 오류 해결 방법


여러 플랫폼에서 작성하는 저장소를 사용하다보면 IDE 설정에 따라 자동으로 소스의 Encoding, Line Ending, BOM(Byte Order Mark)이 변경되는 문제가 있다. 한글이 깨지는 문제도 발생할 수 있고, 이럴 경우 자신이 수정하지 않은 코드도 수정된 것 처럼 나타나기 때문에 커밋 히스토리를 엉망으로 만들어 나중에는 머지할 때마다 문제가 된다. 또한 BOM이 제거될 경우에는 Windows VS Warning Level에 따라 빌드오류까지 야기시킨다. 이를 해결하기 위해 아래 해결법을 제시해본다.

첫 번째로, 이를 해결하기 저장소의 컨벤션을 맞추는 일이다.

프로그래머끼리 convention을 정하여 Encoding, Line Ending을 동일하게 맞추어 개발한다.

  • Encoding: UTF-8 BOM

  • Line Endings: CRLF


  • CR(Carriage Return, \r): 현재 위치에서 바로 아래로 이동.

  • LF(Line Feed, \n): 커서의 위치를 앞으로 이동.


  • 윈도우/DOS: CRLF 조합으로 Line Ending 정의

  • Unix계열(Linux, Darwin): LF로 Line Ending 정의

이래서 Windows에서 작성한 코드를 Unix계열에서 vi로 편집했을 때 ^M이 붙는 것을 볼 수 있다.

두 번째로, Line Ending의 경우 git 설정을 이용하는 방법이 있다.

  • Windows

    core.autocrlf를 true로 설정하면 Checkin할 때 LF를 CRLF로 바꿔준다.

      $ git config --global core.autocrlf true
  • Linux/macOS

    core.autocrlf를 input으로 설정하면 CRLF를 LF로 바꿔서 Commit해준다.

      $ git config --global core.autocrlf input
  • .gitattributes 파일을 이용하는 방법

    저장소의 root에 .gitattributes파일을 만들어 설정하면 git config를 설정하지 않아도 된다. git config로 설정하는 방법보다는 .gitattributes 파일을 이용하는 방법을 추천한다.

      * text=auto

    아래와 같이 명시적으로 설정할 수도 있다.

      * text eol=crlf
      * text eol=lf

    아래 명령어로 현재 저장소에 있는 모든 파일의 라인엔딩을 확인할 수 있다.

      $ git ls-files --eol

세 번째로, git hook 기능을 이용하는 방법이 있다.

Git hook은 클라이언트 훅과 서버 훅이 있으며 그 중에 이번에 사용할 기능은 클라이언트 훅의 커밋 훅을 사용할 것이다. 커밋 훅은 4가지가 있는데 pre-commit을 사용할 것이다. pre-commit의 경우 커밋할 때 가장 먼저 호출되는 훅으로 커밋 메시지 작성하기 전에 호출된다.
hook 기능의 자세한 내용은 추 후에 정리하도록 한다.

사용방법은 저장소의 root에 .git/hooks/pre-commit 스크립트를 만들어 commit할 때 encoding, line-endings를 체크하도록 하여 commit할 때 잘못된 encoding일 경우 0이 아닌 값으로 리턴시키면 커밋이 취소된다. 기본적으로 .git/hook/pre-commit.sample을 제공하고 있으므로 참고할 수 있다.
이를 응용하면 커밋하기전에 lint같은 프로그램으로 코드 스타일을 검사하거나, 특정 파일일 경우 압축할 수 있다.

# pre-commit.sample 기반으로 pre-commit을 작성한다.
$ cd .git/hooks
$ mv pre-commit.sample pre-commit
$ vi pre-commit
# pre-commit을 생략하는 방법으로 --no-verify 옵션을 사용하면 된다.
$ git commit --no-verify

IDE에서 encoding line-ending 변경을 지원하지 않을 경우 vi, vim으로 수정하는 방법을 정리한다.

  • BOM 입력

      :set bomb
  • BOM 제거

      :set nobomb
  • ^M 표시

      :set ffs=unix
      :e filepath
  • ^M 입력

      ctrl + v + m
  • ^M 모두 제거

      :%s/^M//g

서버와 로컬의 라인엔딩이 다를 경우 업데이트하는 방법

중간에 autocrlf 설정을 변경하여 서버와 로컬의 라인엔딩이 꼬이는 경우가 발생할 수 있다.
각각의 파일의 lf와 crlf가 섞이는 경우가 발생한다.
이 때 아래 커맨드로 서버의 라인엔딩을 받아오도록 한다.

git config core.autocrlf false
git add --renormalize [dir|file]

References

https://www.lesstif.com/pages/viewpage.action?pageId=20776404
http://meonggae.blogspot.com/2017/03/git-git-hooks.html

반응형