코드 리뷰, 이슈 보고, 메일로 오가는 패치는 대부분 unified diff 형식입니다. git diff, diff -u, GitHub 의 "raw diff" 가 모두 이 형식을 씁니다. 처음에는 기호가 많아 보이지만 규칙은 단순합니다.
전체 모양
@@ -1,5 +1,6 @@ def greet(name):- print("Hello " + name)+ message = f"Hello, {name}!"+ print(message) def main(): greet("world")
위에서부터 git 확장 헤더, 파일 헤더(---, +++), 헌크(@@ 로 시작하는 덩어리)가 이어집니다. 파일 하나에 헌크가 여러 개일 수 있고, 패치 하나에 파일이 여러 개일 수 있습니다.
파일 헤더: --- 와 +++
--- a/greet.py는 변경 전 파일,+++ b/greet.py는 변경 후 파일입니다.- git 은 경로 앞에
a/,b/를 붙입니다. 그래서patch명령으로 적용할 때-p1로 첫 경로 구성요소를 떼어 냅니다. - 새로 만든 파일은
--- /dev/null, 지운 파일은+++ /dev/null로 표시됩니다. - GNU diff 는 파일 이름 뒤에 수정 시각을 덧붙이기도 합니다.
헌크 헤더 @@ -a,b +c,d @@
@@ -1,5 +1,6 @@ 는 "변경 전 파일의 1번 줄부터 5줄, 변경 후 파일의 1번 줄부터 6줄"을 보여 준다는 뜻입니다.
- 첫 숫자는 시작 줄 번호, 쉼표 뒤는 그 헌크가 차지하는 줄 수(문맥 줄 포함)입니다.
- 줄 수가 1 이면 쉼표와 함께 생략합니다.
@@ -7 +7 @@은 7번 줄 한 줄짜리 헌크입니다. - 줄 수가 0 이면 그쪽에는 줄이 없다는 뜻입니다.
@@ -3,0 +4,2 @@는 원본 3번 줄 뒤에 두 줄이 새로 들어갔다는 의미입니다. 빈 파일과 비교하면-0,0이 나옵니다. - 두 번째
@@뒤에 함수 이름 같은 글이 붙기도 합니다(@@ -40,7 +40,8 @@ def main():). 헌크가 어느 함수 안에 있는지 알려 주는 참고 정보이며, 적용할 때는 무시됩니다.
직접 세어 보면, 위 예제의 문맥 줄(공백으로 시작하는 줄)은 def greet(name):, 빈 줄, def main():, greet("world") 의 4개입니다. 변경 전 줄 수는 문맥 4줄에 - 1줄을 더한 5, 변경 후 줄 수는 문맥 4줄에 + 2줄을 더한 6 이므로 헤더가 -1,5 +1,6 이 됩니다.
본문의 세 가지 줄
| 첫 글자 | 의미 |
|---|---|
| 공백 | 양쪽에 똑같이 있는 문맥 줄 |
- | 변경 전에만 있는 줄(삭제) |
+ | 변경 후에만 있는 줄(추가) |
기본 문맥은 변경 앞뒤 3줄입니다(git diff -U5 처럼 바꿀 수 있음). 문맥 줄은 패치를 적용할 때 올바른 위치를 찾는 데 쓰입니다. 줄 번호가 조금 어긋나도 문맥이 맞으면 patch 는 위치를 옮겨(offset) 적용합니다.
한 줄을 고친 것은 - 줄 다음에 + 줄이 오는 쌍으로 나타납니다. unified 형식에는 "수정"이라는 기호가 따로 없으므로, 연속된 - 묶음과 + 묶음을 위아래로 맞춰 읽는 것이 요령입니다.
\ No newline at end of file
@@ -1,2 +1,2 @@ host=example.com-port=8080\ No newline at end of file+port=8080
바로 위 줄이 파일의 마지막 줄이고 끝에 줄바꿈 문자가 없다는 표시입니다. 위 예에서는 내용은 같고, 변경 후 파일에만 마지막 줄바꿈이 추가됐습니다. 자세한 이야기는 줄 끝 문자와 보이지 않는 차이를 참고하세요.
git 확장 헤더
diff --git a/경로 b/경로 다음 줄들은 git 만의 추가 정보입니다.
index 3b18e51..a6f4c2d 100644— 변경 전후 파일 내용의 해시 앞부분과 파일 모드(100644 는 일반 파일, 100755 는 실행 파일)new file mode 100644/deleted file mode 100644— 파일 생성·삭제old mode 100644/new mode 100755— 실행 권한만 바뀜(내용 헌크 없이 나올 수 있음)similarity index 90%,rename from 옛경로,rename to 새경로— 이름 변경(내용이 90% 같다는 뜻)Binary files a/logo.png and b/logo.png differ— 바이너리 파일은 내용 대신 이 한 줄만
리뷰할 때 쓸 만한 요령
- 헌크 헤더의 줄 수 차이를 먼저 보면 변경의 크기를 짐작할 수 있습니다.
-10,7 +10,30이면 23줄이 늘었습니다. - 공백만 바뀐 헌크를 걸러 내려면
git diff -w를 씁니다. 들여쓰기 정리와 실제 변경이 섞인 커밋을 볼 때 특히 유용합니다(공백 무시 옵션). - 줄 안에서 무엇이 바뀌었는지 보려면
git diff --word-diff를 쓰거나, 이 사이트처럼 줄 안 하이라이트를 지원하는 도구에 넣습니다. - 패치를 적용하기 전에는
git apply --check 파일.patch로 깨끗하게 적용되는지 먼저 확인합니다. git 저장소가 아니면patch -p1 --dry-run < 파일.patch를 씁니다.
이 도구에서 해 보기
텍스트 비교기의 통합 보기는 이 형식과 같은 순서로 - 묶음 다음 + 묶음을 보여 주고, 줄 안의 바뀐 단어를 한 번 더 강조합니다. 결과 막대의 patch 버튼을 누르면 표준 unified diff 텍스트가 복사되고, 옆의 저장 버튼은 diff.patch 파일로 내려받습니다. 무시 옵션을 모두 끈 상태에서 만든 patch 는 patch -p1 이나 git apply 로 원본에 적용할 수 있습니다.