Linux工具篇 | Linux diff与git补丁文件的生成与使用

一、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) - 简书

                  Git 打补丁-- patch 和 diff 的使用(详细) - 简书

                  如何使用git 生成patch 和打入patch_liuhaomatou的专栏-CSDN博客

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式逍遥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值