티스토리 뷰
사내에서 diff와 patch를 다룰 일이 잦아 관련 내용을 정리해보고자 한다.git version 2.39.2 (Apple Git-143)
, patch 2.0-12u11-Apple
에서 확인한 내용이며 버전에 따라 출력 형식은 조금 변할 수 있다.
diff?
git diff
라는 명령으로 사용 가능하다.
깃의 워킹 디렉토리와 스테이징 영역을 비교하거나, 특정 커밋과 비교하거나, 로컬과 원격 깃 레포지토리를 비교하는 명령이다.
diff 사용법
diff
라는 폴더에 first.txt
라는 파일을 생성해 임의의 최초 커밋을 생성한 다음,
second.txt
라는 파일을 생성한 뒤 git log
를 확인한 결과는 아래와 같다.
# git log
commit 8d475c23f8ac7f857ca6f1ab7790f034467e8e55 (HEAD -> main)
Author: ... <...@gmail.com>
Date: Sun Feb 4 15:51:24 2024 +0900
second.txt
commit a9720f836dd6385594dd0e3ac53537c3f63acf03
Author: ... <...@gmail.com>
Date: Sun Feb 4 15:47:16 2024 +0900
create first.txt
git diff HEAD~1..HEAD
로 HEAD
에 위치한 가장 최근 커밋과 첫 번째 커밋을 비교할 수 있다.HEAD
대신 원하는 커밋의 커밋 해시(SHA
)를 지정하여 비교할 수도 있다.
# git diff HEAD~1..HEAD, HEAD의 1개 이전 커밋과 HEAD를 비교, 커밋 해시로도 비교 가능
diff --git a/second.txt b/second.txt
new file mode 100644
index 0000000..86a2422
--- /dev/null
+++ b/second.txt
@@ -0,0 +1 @@
+create second.txt
어떤 디렉토리에 어떤 내용의 파일이 변경되었는지 알려준다.
a/
, b/
??
실제 파일 디렉토리와 무관하게 디렉토리 앞에 a/
, b/
가 붙는 것을 볼 수 있다.
이는 git이 변경 사항을 관리하기 위해 임의로 붙이는 prefix로, 변경 전 디렉토리에는 a/
를, 변경 후 디렉토리에는 b/
를 자동으로 붙여 표현하게 된다.
이러한 prefix 없이 실제 디렉토리만을 표현하고자 한다면 --no-prefix
옵션을 붙이면 된다
--no-prefix
git diff시 출력에 디렉토리에 자동으로 변경 전, 후를 나타내기 위해 붙는 a/
, b/
와 같은 prefix를 제거할 수 있다.
--no-prefix
를 추가해 diff를 출력한 결과는 아래와 같다.
# git diff HEAD~1..HEAD --no-prefix
diff --git second.txt second.txt # 옵션 없이는 diff --git a/second.txt b/second.txt 로 출력되었음
new file mode 100644
index 0000000..86a2422
--- /dev/null
+++ second.txt # 옵션 없이는 b/second.txt로 출력되었음.
@@ -0,0 +1 @@
+create second.txt
file mode?
새로운 변경에 대한 종류 및 권한 또한 표시되는 것을 볼 수 있다.
new file mode 100644
100644
는 파일의 유형 및 권한을 8진수로 표현한 것이다.
앞의 100
은 변경의 유형, 뒤의 644
는 해당 파일의 권한을 나타낸다.
100
은 일반 파일, 644
는 -rw-r--r--
로 소유자의 읽기 쓰기 권한, 그룹의 읽기 권한, 다른 사용자는 읽기 권한을 가진 파일임을 나타낸다.
index?
변경되는 부분이 로컬에서 어떤 해시를 부여받아 추적되는지 나타낸다.
위에서는 새로운 파일을 생성하는 경우이므로 기존 해시가 0000000
였고 새로운 해시가 부여되는 것을 볼 수 있다.
git 버전에 따라 file mode와 index가 같은 행에 표시되는 경우가 존재한다.
/dev/null
?
git
으로 관리되는 프로젝트의 루트 디렉토리에 바로 파일을 생성했음에도 /dev/null
이라는 파일이 사라지고 생성한 파일이 대체한 것으로 표현된다.
/dev/null
은 유닉스 시스템에서 특별하게 다뤄지는 파일로 데이터를 버리고 아무 동작도 하지 않는 파일을 의미한다.
실제로 우리가 생성한 파일과 관계가 없다.
파일 생성, 수정, 삭제, 이름 변경 시의 diff
파일 생성, 수정, 삭제 시의 diff 형태를 한눈에 보면 아래와 같다.
기존의 first.txt
는 삭제, second.txt
는 수정, third.txt
라는 파일은 새로 생성했다.
# 생성, 수정, 삭제 시의 diff
diff --git a/first.txt b/first.txt
deleted file mode 100644
index cbd2c53..0000000
--- a/first.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-create first file
-
diff --git a/second.txt b/second.txt
index 86a2422..3dcf956 100644
--- a/second.txt
+++ b/second.txt
@@ -1 +1,5 @@
+prefix
+
create second.txt
+
+postfix
diff --git a/third.txt b/third.txt
new file mode 100644
index 0000000..a1c5d2c
--- /dev/null
+++ b/third.txt
@@ -0,0 +1,2 @@
+create third.txt
+
# 이름 변경 시의 diff
diff --git a/second.txt b/second_new_name.txt
similarity index 100%
rename from second.txt
rename to second_new_name.txt
patch
git diff
를 통해 얻어낸 변경 사항을 patch
라는 별도의 프로그램을 통해 git
과 무관하게 적용할 수 있다.
patch를 사용하면 변경 내역
을 파일로 관리
, 손쉽게 변경을 적용할 수 있다.
두 사람의 git
디렉토리에 first.txt
만 있는 상황을 가정,
나의 로컬에서의 변경점을 원격 git 레포지토리 활용 없이 타인의 로컬에 반영하려고 한다.
#ls
first.txt
어떠한 작업을 수행하여 결과로 second.txt
가 생성되었고 그 내용을 커밋하였다.
diff
를 출력하면 다음과 같다.
# git diff HEAD~1..HEAD
diff --git a/second.txt b/second.txt
new file mode 100644
index 0000000..86a2422
--- /dev/null
+++ b/second.txt
@@ -0,0 +1 @@
+create second.txt
이 diff
를 단순히 콘솔에 출력하지 않고 파일의 형태로 만들어내면 patch
프로그램에 이를 그대로 적용 가능하다.
diff
가 곧 patch file
이 된다.
# 패치 파일 생성
git diff HEAD~1 HEAD > ../patch_file # 생성을 원하는 디렉토리 및 파일 명 입력
당연히 파일의 내용은 diff
로 출력한 내용과 동일하다.
이제 이 패치 파일을 타인의 로컬에 그대로 전달하고,
아래와 같이 패치 파일 표준 입력으로 넣어주기만 하면 된다.
# patch 적용 전 ls
first.txt
# patch 적용
# patch -p1 < ../patch_file
patching file second.txt
# patch 적용 결과 ls
first.txt second.txt
파일의 형태로 변경 사항을 가볍게 주고받고 적용할 수 있다.
-p1
?
왜 굳이 p1 옵션을 붙이는 것일까?
이것은 패치 파일(diff)에 존재하는 디렉토리 정보에서 경로 정보의 상위 몇 번째 디렉토리까지 무시하고 적용할지 알리는 옵션이다.
위에서 설명했듯 --no-prefix
옵션 없이 패치 파일을 생성(diff
)하면
a/
, b/
와 같이 git이 prefix로 별도 디렉토리 정보를 추가한 결과가 출력되므로,
diff --git a/second.txt b/second.txt # 실제 디렉토리 정보가 아닌 `a/`, `b/`가 포함됨.
new file mode 100644
index 0000000..86a2422
--- /dev/null
+++ b/second.txt
@@ -0,0 +1 @@
+create second.txt
patch 프로그램이 이를 실제로 적용할 때 디렉토리에 붙은 접두어 한 단계를 무시하고 적용하도록 하는 것이다.
당연하게도 만약 --no-prefix
옵션을 주어 패치 파일을 생성했다면,
패치 적용 시에는 patch -p0 < ${patch_file}
로 p0
옵션을 주어야 한다.
패치 파일과 패치 적용 시의 디렉토리 옵션이 맞지 않는 경우 사용자가 직접 이 충돌을 해소해주어야 하며 실패하는 경우 Oops.rej
가 남는다.
참고
단순 파일에 대한 변경의 경우 패치 파일에 권한 및 로컬 깃 인덱스 정보가 누락되어도 적용은 가능하다.
# 파일 권한 및 인덱스 정보가 없는 아래의 약식 패치 파일도 적용이 가능하다.
--- /dev/null
+++ b/second.txt
@@ -0,0 +1 @@
+create second.txt
'기타' 카테고리의 다른 글
[오류] M1 Mac에서 Python MediaPipe 설치 중 OpenCV 관련 오류 (0) | 2022.11.24 |
---|
- Total
- Today
- Yesterday
- springboottest
- logback-spring.xml
- 우테코 5기
- 우테코 프리코스
- 생성자 주입
- Payload 암호화
- Jenkins 예약 배포
- Java
- MySQL
- multiplebagsfetchexception
- JPA
- invokedynamic
- stubbing
- 우테코
- RandomPort
- MySQL 이벤트 스케줄
- GitHub Discussion Template
- Spring Boot Monitoring
- GitHub Discussion
- Spring
- Fromtail
- GitHub Discussion 템플릿
- Spring 테스트
- 자바
- 스프링
- 의존성 주입
- 함수형 인터페이스
- JPA JSON
- java switch case
- 람다식
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |