HOME > git > tips

Git - Patch 만들기 & 적용하기

JSFollow07 Oct 2019

오픈소스 프로젝트에 참여하면 git을 사용하게 되고, patch 파일을 접하게 됩니다. 만약 다른 사람으로부터 patch를 전달받았다면 나의 로컬 소스에 적용할 수 있습니다.

이 글에서는 리눅스 개발환경에서 Git 패치를 만드는 방법과 적용하는 방법을 알아보겠습니다.

git commit 패치 만들기 & 적용

Git을 사용할 때, 다음 명령어를 사용하면 현재 commit부터 입력한 commit 이전까지 패치를 만들어줍니다.

$ git format-patch [commit-id]

실제로 패치를 만들어보면 commit 당 1개의 패치 파일을 만들어줍니다.

$ git log
commit 2eadda0d1931632a4dcdcd2bce170f55dc9928a2 (HEAD -> master)
...
commit 53192f622e94f814f56352248fb33fc7bd017184
...
commit 31c06b3ce501bee7f9a784999337ec72ecdc1bb7

$ git format-patch 31c06b3ce501bee7f9a784999337ec72ecdc1bb7
0001-changes.patch  # => 53192f6 에 대한 패치
0002-changes2.patch # => 2eadda0 에 대한 패치

-[숫자] 옵션을 주면, 현재 commit부터 최신에 반영한 몇번째 commit 까지 패치를 만들 수 있습니다.

$ git format-patch -[패치로 만들 commmit 개수]

예를 들어, 다음과 같이 입력하면 최근에 반영한 commit 2개를 패치로 만들어 줍니다.

$ git format-patch -2
0001-changes.patch
0002-changes2.patch

만들어진 패치를 git 프로젝트에 적용하려면 다음 명령어를 사용하면 됩니다. 패치가 적용되면 commit까지 반영된 상태가 됩니다.

$ git am [patch file]

패치 적용에 성공하면 다음과 같은 로그가 나오고, merge 과정에서 conflict이 발생하면 에러 로그가 출력됩니다.

$ git am 0001-changes.patch
Applying: changes
$ git am 0002-changes2.patch
Applying: changes2

git diff 패치 만들기 & 적용

git commit이 아닌 git diff에 대해서 패치를 만드려면 다음과 같이 하시면 됩니다.

$ git diff > patchfile

그럼 다음처럼 패치 파일이 만들어집니다.

$ cat patchfile
diff --git a/patch-515db99 b/patch-515db99
deleted file mode 100644
index e69de29..0000000
diff --git a/src/main/java/hello/HelloWorld.java b/src/main/java/hello/HelloWorld.java
index 576a0c7..650be6d 100644
--- a/src/main/java/hello/HelloWorld.java
+++ b/src/main/java/hello/HelloWorld.java
@@ -4,6 +4,7 @@ public class HelloWorld {
     public static void main(String[] args) {
         Greeter greeter = new Greeter();
         String suffix = "@@@";
-        System.out.println(greeter.sayHello() + suffix);
+        String prefix = "$$$"
+        System.out.println(prefix + greeter.sayHello() + suffix);
     }
 }

패치를 적용하시려면 다음 명령어를 사용하시면 됩니다. 여기서 옵션은 -p1을 적용해야 합니다.

patch -p1 < patch123

패치 적용 후, git diff를 해보면 적용된 것을 확인할 수 있습니다.

$ git diff
diff --git a/patch-515db99 b/patch-515db99
deleted file mode 100644
index e69de29..0000000
diff --git a/src/main/java/hello/HelloWorld.java b/src/main/java/hello/HelloWorld.java
index 576a0c7..650be6d 100644
--- a/src/main/java/hello/HelloWorld.java
+++ b/src/main/java/hello/HelloWorld.java
@@ -4,6 +4,7 @@ public class HelloWorld {
     public static void main(String[] args) {
         Greeter greeter = new Greeter();
         String suffix = "@@@";
-        System.out.println(greeter.sayHello() + suffix);
+        String prefix = "$$$"
+        System.out.println(prefix + greeter.sayHello() + suffix);
     }
 }

--no-prefix 옵션을 주어 패치를 만들 수 있습니다. 이 옵션을 주면 a/b path prefix가 제거된 패치가 만들어집니다. 주의할 점은 패치를 적용할 때는 -p0옵션을 주어야 합니다.

$ git diff --no-prefix > patch123
$ patch -p0 < patch123