개발하다 보면 diff를 봐야할 경우가 많습니다. 형상관리를 쓰다 보면 diff를 볼 일이 더 많습니다. 저는 Git을 주로 사용하는데, diff를 볼 때 짜증 나는 점이 있었습니다.

  1. 바꾸지 않은 줄이 바뀌었다고 나온다.
  2. 줄에 바뀐 게 있다는 건 알겠는데 어디가 바뀌었는지 모르겠다.

이 문제는 어떻게 해결할까요?

정말 바꾼 줄만 diff 처리 되도록

바꾸지 않은 줄이 바뀌었다고 나오는 경우는 이런 경우입니다.

변경 전 파일

for n in range(10):
    print('강아지 {}마리'.format(n))

for n in range(10):
    print('냐옹이 {}마리'.format(n))

변경 후 파일

for n in range(10):
    print('강아지 {}마리'.format(n))

for n in range(10):
    print('햄스터 {}마리'.format(n))

for n in range(10):
    print('냐옹이 {}마리'.format(n))

git diff로 나오는 것

diff --git a/test.py b/test.py
index 90cc286..4c4ef22 100644
--- a/test.py
+++ b/test.py
@@ -2,6 +2,9 @@ for n in range(10):
     print('강아지 {}마리'.format(n))

 for n in range(10):
+    print('햄스터 {}마리'.format(n))
+
+for n in range(10):
     print('냐옹이 {}마리'.format(n))

제가 추가한 단락이 이상하게 인식되어 있습니다. diff를 보고 이해할 수 없는 수준은 아니지만, 가독성이 떨어집니다.

편하게 바꾸기

이 기능은 Git 2.9에 공식 기능으로 추가되었습니다.12 기능을 이용하기 위해서 일단 Git 2.9.0 이상을 설치해주세요.

설치하고 난 다음엔 똑똑해진 휴리스틱을 적용할 수 있습니다.

$ git config --global diff.compactionHeuristic true

다시 diff를 뽑아보면 다음과 같이 나옵니다.3

diff --git a/test.py b/test.py
index 3d6a073..edf9b3c 100644
--- a/test.py
+++ b/test.py
@@ -1,6 +1,9 @@
 for n in range(10):
     print('강아지 {}마리'.format(n))

+for n in range(10):
+    print('햄스터 {}마리'.format(n))
+
 for n in range(10):
     print('냐옹이 {}마리'.format(n))

이제 제가 추가한 단락이 제대로 인식되고 있습니다.

줄에서 어느 글자가 바뀌었는지

Git diff는 기본적으로 어느 줄이 바뀌었는지는 알려주지만, 어느 글자가 바뀌었는지는 알려주지 않습니다. 그렇게 되면 실수가 섞여 있다던가 하는 경우의 확인이 힘듭니다.

변경 전 소스

hello 1
hello 2
hi 3

변경 후 소스

Hello 1
Hello 2
Hello 3

git diff로 나오는 것

git diff

어느 글자가 바뀌었는지는 사람 눈으로 직접 찾아야 합니다.

편하게 바꾸기

diff-highlight를 사용하면 됩니다. 이 기능은 사실 Git 자체의 기능은 아니지만, 상당히 예전부터 Git-core에 contrib으로써 같이 배포되고 있었습니다.

Ubuntu(15.04)의 경우 apt(apt-get)을 통해 설치하면 contrib이 빠져있습니다. Mac OS X의 경우도 Xcode에 첨부된 git에는 포함되어 있지 않습니다. 하지만 diff-highlight는 단순한 shell script이므로 원하는 경로에 다음 내용의 파일을 diff-highlight 라는 파일명으로 만들어주세요. 주의하실 점은 실행권한을 주셔야만 합니다.

Mac OS X에서 Gitd을 brew로 설치한 경우에는 /usr/local/share/git-core/contrib/diff-highlight/diff-highlight이 있습니다.

이 기능을 두고두고 쓰게 될 가능성이 높으니 diff-highlight가 위치하는 곳을 PATH 환경변수에 추가합시다.4

$ export PATH="/usr/local/share/git-core/contrib/diff-highlight/:${PATH}"

그러고 나서 Git의 설정을 변경하면 됩니다.

$ git config --global pager.log 'diff-highlight | less'
$ git config --global pager.show 'diff-highlight | less'
$ git config --global pager.diff 'diff-highlight | less'

Git 2.9부터는 interactive staging에도 적용할 수 있습니다.5

git config --global interactive.diffFilter diff-highlight

git diff

바뀐 글자에 하이라이팅이 되는 것을 확인할 수 있습니다.

더 예쁘게

diff-so-fancy라는 프로젝트를 사용하면 됩니다. 제 경우는 diff를 타인과 공유해야 할 가능성을 생각해서 사용하지 않았지만, 단순히 보기 편하게 하는 것이 목적이라면 훌륭하다고 생각합니다.

원상복구

본 게시물에서는 설정 변경에 모두 --global flag를 달아두었습니다. 즉, 모든 설정이 전역에 적용됩니다. 전역 설정에서 되돌리면 되는데, ~/.gitconfig 파일을 열어서 없애고 싶은 설정을 제거하시면 원상 복구됩니다.


  1. https://github.com/git/git/commit/0018da1088e3d7e282998d80db3c719fa7a18ce3

  2. https://github.com/git/git/commit/5580b271af518bae30148edfd42cc8459d8da384

  3. 두 출력물을 서로 다른 컴퓨터에서 진행하여서 Git revision이 다르게 나오고 있습니다. 이 부분은 테스트를 위한 부분이었으므로 별로 중요하지 않습니다.

  4. PATH 환경변수에 추가한 내용이 다시 터미널을 열어도 유지되게 하는 방법은 이 글의 범주 밖이므로 다루지 않습니다.

  5. https://github.com/git/git/commit/5580b271af518bae30148edfd42cc8459d8da384