一、diff 命令生成的补丁
(1)补丁文件的生成
在某一目录下新建目录patch-test-new与patch-test-old:
~/Study/patch$ ls
patch-test-new patch-test-old
分别在目录patch-test-new与patch-test-old创建test.c内容如下:
~/Study/patch/patch-test-new$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
return 0;
}
~/Study/patch/patch-test-old$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
return 0;
}
可以看出目录patch-test-new下的test.c多了一行打印!下面回到两个目录的顶层目录下,执行如下命令生成补丁文件:
~/Study/patch$ diff -urN patch-test-old/ patch-test-new/ > patch-test.patch
diff参数选项的作用:
- -u:表示在比较结果中输出上下文中一些相同的行,这有利于人工定位
- -r:表示递归比较各个子目录下的文件
- -N:将不存在的文件当作空文件
另外有两个参数也可能会用到:
- -w:忽略对空格的比较
- -B:忽略对空行的比较
(2)补丁文件的内容
~/Study/patch$ cat patch-test.patch
diff -urN patch-test-old/test.c patch-test-new/test.c
--- patch-test-old/test.c 2020-10-10 20:09:49.050955538 +0800
+++ patch-test-new/test.c 2020-10-10 20:10:50.174934326 +0800
@@ -3,5 +3,6 @@
int main()
{
printf("hello world");
+ printf("neutionwei");
return 0;
}
第一部分为第1行,它是制作补丁所使用的命令,后面的是两个工程目录的文件。
第二部分为第2、3行,“---”表示原始文件,“+++”表示修改过的文件。
剩下的是第三部分,“@@ -3,5 +3,6 @@”中的“-3,5”表示原始文件的第3行到第5行,“+3,6”表示修改过的文件的第3行到第6行。两者之差的内容即为修改的内容,其中减号(“-”)表示删除,加号(“+”)表示添加。
(3)打补丁
进入到目录patch-test-old,执行如下命令打补丁:
~/Study/patch/patch-test-old$ patch -p1 < ../patch-test.patch
再次查看test.c,发现与目录patch-test-old的test.c内容一致:
~/Study/patch/patch-test-old$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
return 0;
}
(4)卸载补丁
进入到目录patch-test-old,执行如下命令卸载补丁:
~/Study/patch/patch-test-old$ patch -p1 < ../patch-test.patch
patching file test.c
再次查看test.c,发现内容变回到最初:
~/Study/patch/patch-test-old$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
return 0;
}
二、git 生成的补丁
新建目录并初始化git仓库:
~/Study/git-patch$ git init
Initialized empty Git repository in /home/book/Study/git-patch/.git/
~/Study/git-patch$ git status
On branch master
Initial commit
nothing to commit (create/copy files and use "git add" to track)
~/Study/git-patch$ cp ../patch/patch-test
patch-test-new/ patch-test-old/ patch-test.patch
~/Study/git-patch$ cp ../patch/patch-test-
patch-test-new/ patch-test-old/
~/Study/git-patch$ cp ../patch/patch-test-old/test.c .
~/Study/git-patch$ ls
test.c
~/Study/git-patch$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
test.c
nothing added to commit but untracked files present (use "git add" to track)
提交三个commit:
~/Study/git-patch$ git add test.c
~/Study/git-patch$ git commit -m "create a test.c file"
[master (root-commit) 5458a79] create a test.c file
1 file changed, 7 insertions(+)
create mode 100644 test.c
/Study/git-patch$ git log
commit 5458a799aef9ab14942b93be872ec3074261efff
Author: NeutionWei <1037508099@qq.com>
Date: Sun Oct 11 10:34:05 2020 +0800
create a test.c file
...................................................................................
~/Study/git-patch$ git log
commit d29174b17bbd285ededeb88b26875a90673bec71
Author: NeutionWei <1037508099@qq.com>
Date: Sun Oct 11 10:39:40 2020 +0800
add csdn blog https address
commit 9f1e6d397683fb38fd73c9eeb04f43364ca8fc9e
Author: NeutionWei <1037508099@qq.com>
Date: Sun Oct 11 10:38:10 2020 +0800
add printf neutionwei
commit 5458a799aef9ab14942b93be872ec3074261efff
Author: NeutionWei <1037508099@qq.com>
Date: Sun Oct 11 10:34:05 2020 +0800
create a test.c file
(1)git format-patch 命令生成的补丁
~/Study/git-patch$ git format-patch d29174b17bbd285ededeb88b26875a90673bec71 -2
0001-add-printf-neutionwei.patch
0002-add-csdn-blog-https-address.patch
查看补丁文件:
~/Study/git-patch$ ls
0001-add-printf-neutionwei.patch 0002-add-csdn-blog-https-address.patch test.c
~/Study/git-patch$ cat 0001-add-printf-neutionwei.patch
From 9f1e6d397683fb38fd73c9eeb04f43364ca8fc9e Mon Sep 17 00:00:00 2001
From: NeutionWei <1037508099@qq.com>
Date: Sun, 11 Oct 2020 10:38:10 +0800
Subject: [PATCH 1/2] add printf neutionwei
---
test.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/test.c b/test.c
index 73a8f3a..b237ba7 100644
--- a/test.c
+++ b/test.c
@@ -3,5 +3,6 @@
int main()
{
printf("hello world");
+ printf("neutionwei");
return 0;
}
--
2.7.4
(2)git diff 命令生成的补丁
~/Study/git-patch$ git diff d29174b17bbd285ededeb88b26875a90673bec71 9f1e6d397683fb38fd73c9eeb04f43364ca8fc9e > test-remove-address.diff
~/Study/git-patch$ cat test-remove-address.diff
diff --git a/test.c b/test.c
index 2e1293f..b237ba7 100644
--- a/test.c
+++ b/test.c
@@ -4,6 +4,5 @@ int main()
{
printf("hello world");
printf("neutionwei");
- printf("https://blog.csdn.net/Neutionwei");
return 0;
}
~/Study/git-patch$ git diff 9f1e6d397683fb38fd73c9eeb04f43364ca8fc9e d29174b17bbd285ededeb88b26875a90673bec71 > test-add-address.diff
~/Study/git-patch$ cat test-add-address.diff
diff --git a/test.c b/test.c
index b237ba7..2e1293f 100644
--- a/test.c
+++ b/test.c
@@ -4,5 +4,6 @@ int main()
{
printf("hello world");
printf("neutionwei");
+ printf("https://blog.csdn.net/Neutionwei");
return 0;
}
可见它是从commit前后顺序的对比来生成补丁文件的!
(3)git apply命令打补丁
a、diff文件打补丁
查看补丁文件是否可以使用,若终端无打印则表示可以使用:
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
printf("https://blog.csdn.net/Neutionwei");
return 0;
}
~/Study/git-patch$ git apply --check test-add-address.diff
error: patch failed: test.c:4
error: test.c: patch does not apply
~/Study/git-patch$ git apply --check test-remove-address.diff
打补丁:
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
printf("https://blog.csdn.net/Neutionwei");
return 0;
}
~/Study/git-patch$ git apply test-remove-address.diff
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
return 0;
}
可见 printf("https://blog.csdn.net/Neutionwei"); 语句被去掉了!
b、patch文件打补丁
首先切换到最初的commit:
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
printf("https://blog.csdn.net/Neutionwei");
return 0;
}
~/Study/git-patch$ git checkout 5458a799aef9ab14942b93be872ec3074261efff
Note: checking out '5458a799aef9ab14942b93be872ec3074261efff'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at 5458a79... create a test.c file
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
return 0;
}
检查补丁并打补丁:
~/Study/git-patch$ git apply --check 0001-add-printf-neutionwei.patch
~/Study/git-patch$ git apply 0001-add-printf-neutionwei.patch
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
return 0;
}
去除补丁:
~/Study/git-patch$ git apply -R 0001-add-printf-neutionwei.patch
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
return 0;
}
(4)git am命令打补丁
一次性打上所有patch文件:
~/Study/git-patch$ ls
0001-add-printf-neutionwei.patch test-add-address.diff test-remove-address.diff
0002-add-csdn-blog-https-address.patch test.c
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
return 0;
}
~/Study/git-patch$ git am --abort
~/Study/git-patch$ git am *.patch
Applying: add printf neutionwei
Applying: add csdn blog https address
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
printf("https://blog.csdn.net/Neutionwei");
return 0;
}
单独打某个patch文件:
~/Study/git-patch$ ls
0001-add-printf-neutionwei.patch test-add-address.diff test-remove-address.diff
0002-add-csdn-blog-https-address.patch test.c
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
return 0;
}
~/Study/git-patch$ git am --abort
~/Study/git-patch$ git am 0001-add-printf-neutionwei.patch
Applying: add printf neutionwei
~/Study/git-patch$ git am 0002-add-csdn-blog-https-address.patch
Applying: add csdn blog https address
~/Study/git-patch$ cat test.c
#include <stdio.h>
int main()
{
printf("hello world");
printf("neutionwei");
printf("https://blog.csdn.net/Neutionwei");
return 0;
}
参考资料:Git补丁 - mic_yx - 博客园
Git 生成补丁与打补丁(生成Patch和打Patch) - 简书