Tools mentioned in this article
Open the browser-based tool while you read and try the workflow immediately.
@@ -12,7 +12,9 @@ 를 읽을 수 있으면 diff는 어렵지 않다
git diff 출력에서 많은 사람이 그냥 넘기는 줄이 이것입니다.
@@ -12,7 +12,9 @@ export function calculateTotal(items) {
+ 와 - 의 의미는 누구나 알지만, 이 네 개의 숫자가 무엇을 가리키는지 설명할 수 있는 사람은 의외로 적습니다. 이걸 읽을 수 있으면 리뷰의 정확도가 올라가고, 패치 적용 실패나 충돌의 원인도 훨씬 쉽게 짚어낼 수 있습니다.
이 글은 unified diff 형식을 한 조각씩 뜯어보는 레퍼런스입니다.
전체 구조
전형적인 출력은 세 층으로 되어 있습니다.
diff --git a/src/cart.js b/src/cart.js ← 어떤 파일인지
index 83db48f..bf269f4 100644 ← 변경 전후의 오브젝트 ID와 권한
--- a/src/cart.js ← 변경 전(a)
+++ b/src/cart.js ← 변경 후(b)
@@ -12,7 +12,9 @@ export function calculateTotal(items) { ← 헝크 헤더
const subtotal = items.reduce(...) ← 컨텍스트 줄(맨 앞이 공백)
- return subtotal; ← 삭제된 줄
+ const tax = subtotal * 0.1; ← 추가된 줄
+ return subtotal + tax;
}
a/ 와 b/ 는 ‘변경 전’, ‘변경 후’ 를 뜻하는 관례적인 접두사이며 실제 디렉터리가 아닙니다. 새 파일이면 --- /dev/null, 삭제면 +++ /dev/null 이 됩니다.
헝크 헤더의 네 숫자
@@ -12,7 +12,9 @@
│ │ │ └── 변경 후: 그 위치부터 9줄
│ │ └───── 변경 후: 12번째 줄부터
│ └──────── 변경 전: 그 위치부터 7줄
└─────────── 변경 전: 12번째 줄부터
즉 -시작줄,줄수 +시작줄,줄수 입니다. 핵심은 줄수가 ‘바뀐 줄의 수’가 아니라 ‘그 헝크가 다루는 범위의 크기’ 라는 점으로, 컨텍스트 줄도 포함됩니다. 위 예시는 7줄이 9줄이 되었다, 즉 순증 2줄로 읽습니다.
줄수가 1이면 생략되어 @@ -1 +1 @@ 형태가 됩니다. 닫는 @@ 뒤에 붙는 텍스트는 git이 위쪽으로 올라가며 들여쓰기가 얕은 줄을 찾아 추측한 섹션 제목으로, 변경 내용 자체가 아닙니다.
줄 맨 앞의 한 글자가 전부를 결정한다
| 접두 | 의미 |
|---|---|
| (공백) | 컨텍스트 줄, 변경되지 않음 |
- | 변경 전에만 있는 줄(삭제) |
+ | 변경 후에만 있는 줄(추가) |
\ | 파일 자체에 대한 주석(아래 참조) |
‘줄을 수정했다’는 개념은 존재하지 않습니다. 한 글자만 고친 줄도 삭제와 추가의 조합으로 표현됩니다. diff를 읽을 때 가장 크게 헷갈리는 지점으로, 빨강과 초록이 잔뜩 늘어서 있어도 실제로는 세미콜론 하나만 달라진 경우가 흔합니다.
줄 ‘안에서’ 무엇이 바뀌었는지 알고 싶다면 단어 단위로 비교해야 합니다. git이라면 git diff --word-diff, 브라우저라면 텍스트 비교(Diff) 도구 에 붙여 넣어 확인할 수 있습니다.
컨텍스트는 기본 3줄
변경된 줄의 앞뒤에 보이는 변경 없는 줄이 ‘컨텍스트’이며 기본값은 3줄입니다. 패치를 적용하는 쪽은 이 주변이 일치하는지를 보고 ‘붙일 위치’를 찾습니다. 줄 번호가 밀려도 패치가 적용되는 이유가 이것이고, 반대로 그 주변까지 수정되어 있으면 패치는 실패합니다.
git diff -U0 # 컨텍스트 없이 변경된 줄만
git diff -U10 # 앞뒤 10줄씩
\ No newline at end of file
-const config = {};
\ No newline at end of file
+const config = {};
이 주석은 파일 끝에 줄바꿈이 없다는 뜻입니다. 내용이 같아 보이는데 diff가 생긴다면 끝의 줄바꿈이 추가되었거나 사라진 것입니다. 에디터나 .editorconfig(insert_final_newline) 설정으로 의도치 않게 바뀌기 쉬워 리뷰의 잡음이 됩니다.
공백만 바꿨는데 줄 전체가 바뀐 것처럼 보이는 이유
들여쓰기를 탭에서 공백으로 바꾸거나 줄 끝 공백을 지우면 줄의 내용이 달라진 것으로 판정되므로, 화면상 변화가 없어도 해당 줄들이 전부 -/+ 쌍으로 나옵니다.
git diff -w # 공백 양의 차이를 무시
git diff --ignore-blank-lines # 빈 줄의 증감을 무시
줄바꿈 문자(LF와 CRLF)도 같은 이유로 ‘전체 줄이 바뀐’ 것처럼 보입니다. Windows와 Linux가 섞인 저장소에서 한 줄도 건드리지 않았는데 전체 diff가 뜬다면 먼저 이것을 의심하세요.
머지 커밋에 나오는 @@@
충돌을 해결한 머지 커밋을 git show 로 보면 @ 가 세 개 붙은 헤더가 나올 수 있습니다.
@@@ -12,7 -12,8 +12,9 @@@
이는 combined diff 로, 두 부모 각각과의 차이를 동시에 보여줍니다. 접두 열도 두 개가 되어 첫 번째는 첫 부모와의 차이, 두 번째는 두 번째 부모와의 차이를 나타냅니다. 양쪽 부모 모두와 다른 줄만 표시되므로, 머지를 해결하면서 손으로 고친 부분만 정확히 볼 수 있습니다.
이름 변경은 기록이 아니라 추측이다
diff --git a/src/utils.js b/src/helpers.js
similarity index 95%
rename from src/utils.js
rename to src/helpers.js
git은 이름 변경을 기록하지 않습니다. diff를 만들 때 내용의 유사도로 추측하며, 기본적으로 50% 이상 비슷하면 이름 변경으로 보고 그 비율을 similarity index 로 표시합니다. 파일명을 바꾸면서 같은 커밋에서 크게 다시 쓰면 이름 변경으로 인식되지 않고 ‘삭제 + 새 파일’로 표시됩니다.
로컬에서 비교하기
커밋되지 않은 텍스트나 git 밖에 있는 로그·설정 파일을 비교하고 싶다면 텍스트 비교(Diff) 도구 에 두 내용을 붙여 넣으면 변경 부분이 색으로 정렬되어 나옵니다. 브라우저 안에서 처리가 끝나므로 운영 설정 파일이나 로그처럼 밖으로 내보내고 싶지 않은 내용도 그대로 비교할 수 있습니다.
비교 전에 정렬해 두면 diff가 읽기 쉬워집니다. JSON은 JSON 포매터, SQL은 SQL 포매터 로 정리한 뒤 비교하면 의미 있는 차이만 남습니다. diff의 기본(행 단위와 단어 단위의 차이, 공백 처리)은 텍스트 차이 읽는 법과 활용법 에 정리했습니다.
정리
@@ -12,7 +12,9 @@는-시작줄,줄수 +시작줄,줄수. 줄수는 컨텍스트를 포함한 범위이지 변경된 줄 수가 아니다- 맨 앞 한 글자(공백/
-/+)가 전부. ‘수정’은 없고 삭제 + 추가로 표현된다 - 컨텍스트는 기본 3줄. 패치는 이 주변의 일치로 위치를 찾으므로 줄 번호가 밀려도 적용된다
\ No newline at end of file은 끝 줄바꿈의 유무. 유령 diff의 단골 원인- 공백·줄바꿈 문자만의 변경은 전체 diff처럼 보인다.
git diff -w로 구분하자 @@@는 머지 커밋의 combined diff(두 부모와의 차이를 동시 표시)- 이름 변경은 기록이 아니라 유사도 기반 추측(
similarity index)
자주 묻는 질문
@@ -12,7 +12,9 @@ 의 숫자는 무엇을 뜻하나요?
- 쪽이 변경 전, + 쪽이 변경 후이며 각각 ‘시작 줄 번호, 줄 수’ 입니다. 이 예시라면 변경 전은 12번째 줄부터 7줄, 변경 후는 12번째 줄부터 9줄이 대상 범위입니다. 줄 수에는 변경되지 않은 컨텍스트 줄도 포함되므로 편집된 줄 수 자체는 아닙니다.
한 글자만 고쳤는데 줄 전체가 diff로 나오는 이유는?
unified diff 형식에는 ‘줄을 수정했다’는 표현이 없어 모든 변경이 삭제(-)와 추가(+)의 조합으로 표현되기 때문입니다. 줄 안에서 무엇이 바뀌었는지 보려면 git diff --word-diff 를 쓰거나 단어 단위로 비교하는 도구를 사용하세요.
아무것도 편집하지 않았는데 모든 줄이 변경으로 나옵니다
거의 대부분 줄바꿈 문자(LF와 CRLF)나 들여쓰기 공백입니다. git diff -w 로 diff가 사라진다면 원인이 그것입니다. 저장소 전체에서 통일하려면 .gitattributes 로 줄바꿈 문자를 고정하는 방법이 있습니다.
붙여 넣은 내용이 전송되나요?
아니요. 텍스트 비교(Diff) 도구 는 브라우저 안에서 처리가 끝나며, 붙여 넣은 내용이 서버로 전송되는 일은 없습니다. 운영 설정 파일이나 로그 비교에도 그대로 쓸 수 있습니다.