likes
comments
collection
share

GIT diff与patch入门介绍

作者站长头像
站长
· 阅读数 7

在git中,有两种打补丁的方式,一种是diff文件,生成的是unix标准补丁,另一种是patch文件,生成的是git专用补丁。

  • diff只会生成文件的改动信息,不会记录commit信息,多个commit可以合成一个diff文件
  • patch不光会记录文件改动信息,还会记录commit信息,例如commiter,commit date等,每个commit都会单独生成一个patch文件(因为里面包含commit信息)

diff 文件

diff --git a/a.txt b/a.txt                                                                                                                                                                                  
index 52295a4..469cdef 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,3 @@
 wo shi lightingsui
+
+wo yao shengcheng diff wenjian

patch文件

From 275803519accd2b4e89e20803ccc1814b8154c18 Mon Sep 17 00:00:00 2001
From: coolsui <coolsui@126.com>
Date: Thu, 24 Feb 2022 10:46:57 +0800
Subject: [PATCH] edit diff file

Signed-off-by: coolsui <coolsui@126.com>
---
 a.txt    | 2 ++
 sui.diff | 0
 2 files changed, 2 insertions(+)
 create mode 100644 sui.diff

diff --git a/a.txt b/a.txt
index 52295a4..469cdef 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,3 @@                                                                                                                                                                                               
 wo shi lightingsui
+
+wo yao shengcheng diff wenjian
diff --git a/sui.diff b/sui.diff
new file mode 100644
index 0000000..e69de29
-- 
2.17.1

生成patch

现在有三次commit,如下

commit c3c74a0c4a1237a0f0f80b33c4d17dd13538789d (HEAD -> sui)
Author: coolsui <coolsui@126.com>
Date:   Thu Feb 24 15:08:07 2022 +0800

    switch sui branch and edit a.txt

diff --git a/a.txt b/a.txt
index 469cdef..7d1ad46 100644
--- a/a.txt
+++ b/a.txt
@@ -1,3 +1,5 @@
 wo shi lightingsui
 
 wo yao shengcheng diff wenjian
+
+wo switch sui branch

commit 8472d9ba2fbb57ea8f2fd84290883ff55ba2a7a6
Author: coolsui <coolsui@126.com>
Date:   Thu Feb 24 11:09:50 2022 +0800

    edit a.txt
    
    Signed-off-by: coolsui <coolsui@126.com>

diff --git a/a.txt b/a.txt
index 52295a4..469cdef 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,3 @@
 wo shi lightingsui
+
+wo yao shengcheng diff wenjian

commit d3d623ff40dcfc2ef07c2499f2d20a05b6c16a8a
Author: coolsui <coolsui@126.com>
Date:   Thu Feb 24 10:44:21 2022 +0800

    add a.txt
    
    Signed-off-by: coolsui <coolsui@126.com>

diff --git a/a.txt b/a.txt
new file mode 100644
index 0000000..52295a4
--- /dev/null
+++ b/a.txt
@@ -0,0 +1 @@
+wo shi lightingsui

生成diff补丁

命令格式: git diff sha1 sha2 > diffname

对上面的c3c74a0c4a1237a0f0f80b33c4d17dd13538789d8472d9ba2fbb57ea8f2fd84290883ff55ba2a7a6生成diff文件

git diff d3d623ff40dcfc2ef07c2499f2d20a05b6c16a8a c3c74a0c4a1237a0f0f80b33c4d17dd13538789d > 0001.diff
diff --git a/a.txt b/a.txt                                                                                                                                                                                  
index 52295a4..7d1ad46 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,5 @@
 wo shi lightingsui
+
+wo yao shengcheng diff wenjian
+
+wo switch sui branch

sha1为左区间的commit,sha2为右区间的commit,diff文件的范围(sha1, sha2]

生成patch补丁

对上面 c3c74a0c4a1237a0f0f80b33c4d17dd13538789d 生成 patch

命令格式:git format-patch sha -n

n的含义是对指定的 sha 表示的 commit 向前打 n 个commit(包含当前commit)的patch,为1时仅对当前 sha 表示的 commit 打 patch

sui@home:~/me/tmp/test$ git format-patch c3c74a0c4a1237a0f0f80b33c4d17dd13538789d -1
0001-switch-sui-branch-and-edit-a.txt.patch
From c3c74a0c4a1237a0f0f80b33c4d17dd13538789d Mon Sep 17 00:00:00 2001                                                                                                                                      
From: coolsui <coolsui@126.com>
Date: Thu, 24 Feb 2022 15:08:07 +0800
Subject: [PATCH] switch sui branch and edit a.txt

---
 a.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/a.txt b/a.txt
index 469cdef..7d1ad46 100644
--- a/a.txt
+++ b/a.txt
@@ -1,3 +1,5 @@
 wo shi lightingsui

 wo yao shengcheng diff wenjian
+
+wo switch sui branch
-- 
2.17.1

patch 文件不光生成了 diff 信息,还生成了 commit 信息。

当n 指定的数大于1时,会生成多个patch文件,每个commit生成一个文件

sui@home:~/me/tmp/test$ git format-patch c3c74a0c4a1237a0f0f80b33c4d17dd13538789d -2
0001-edit-a.txt.patch
0002-switch-sui-branch-and-edit-a.txt.patch

文件命名格式为: patch自增编号-commit title.txt.patch

应用patch

无论是patch还是diff文件,都可以被应用,例如代码转移操作

git apply

命令格式: git apply filename

无冲突合入

# --check 进行合入预检查,无任何输出代表检查通过
sui@home:~/me/tmp/test$ git apply --check 0001.diff

# 应用diff
sui@home:~/me/tmp/test$ git apply 0001.diff
# 无任何输出证明合入diff代码完成
sui@home:~/me/tmp/test$ 

使用apply应用diff文件或者patch文件并不会自动commit,可以使用git status查看(刚刚应用的diff文件中的修改现在状态为not staged)

sui@home:~/me/tmp/test$ git status
On branch sui
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   a.txt

发生冲突

# 检查失败
sui@home:~/me/tmp/test$ git apply --check 0001.diff
error: patch failed: a.txt:1
error: a.txt: patch does not apply

# 合入失败
sui@home:~/me/tmp/test$ git apply 0001.diff
error: patch failed: a.txt:1
error: a.txt: patch does not apply

一旦repo中的文件和diff冲突,会提示无法合入,但不显示冲突的详细信息(只显示的发生冲突的位置在a.txt文件中)

可以使用git apply --reject filename,该命令会生成一个以发生冲突文件命名的以.rej结尾的文件,该文件显示了发生冲突的信息

sui@home:~/me/tmp/test$ git apply --reject  0001-edit-a.txt.patch
Checking patch a.txt...
error: while searching for:
wo shi lightingsui

error: patch failed: a.txt:1
Applying patch a.txt with 1 reject...
Rejected hunk #1.

sui@home:~/me/tmp/test$ ls
0001-edit-a.txt.patch  0002-switch-sui-branch-and-edit-a.txt.patch  a.txt  a.txt.rej
sui@home:~/me/tmp/test$ cat a.txt.rej 
diff a/a.txt b/a.txt	(rejected hunks)
@@ -1 +1,3 @@
 wo shi lightingsui
+
+wo yao shengcheng diff wenjian

根据冲突文件的信息,进行处理,处理完成后删除掉rej信息,commit即可

git am

命令格式: git am filename

无冲突合入

sui@home:~/me/tmp/test$ ls
0001-edit-a.txt.patch  0002-switch-sui-branch-and-edit-a.txt.patch  a.txt

# 批量合入 patch,代表两次 commit
sui@home:~/me/tmp/test$ git am *.patch
Applying: edit a.txt
Applying: switch sui branch and edit a.txt

因为patch文件携带commit信息,合入后不需要手动commit,会直接commit

sui@home:~/me/tmp/test$ git log
commit e0c28f3d46940580cb42cc981f13327969169a1b (HEAD -> sui)
Author: coolsui <coolsui@126.com>
Date:   Thu Feb 24 15:08:07 2022 +0800

    switch sui branch and edit a.txt

commit 3ff2070a73b5ade9262f5bace7ee2ae373c048b5
Author: coolsui <coolsui@126.com>
Date:   Thu Feb 24 11:09:50 2022 +0800

    edit a.txt
    
    Signed-off-by: coolsui <coolsui@126.com>

commit d3d623ff40dcfc2ef07c2499f2d20a05b6c16a8a
Author: coolsui <coolsui@126.com>
Date:   Thu Feb 24 10:44:21 2022 +0800

    add a.txt
    
    Signed-off-by: coolsui <coolsui@126.com>

发生冲突

sui@home:~/me/tmp/test$ git am *.patch
Applying: edit a.txt
error: a.txt: does not match index
Patch failed at 0001 edit a.txt
Use 'git am --show-current-patch' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

发生冲突后,提供三个命令用来处理冲突

# 处理完冲突后(需使用git add命令), 执行该命令,继续合入操作
git am --continue

# 跳过冲突
git am --skip

# 终止合入,恢复到应用该path之前的状态
git am --abort

apply与am区别

  1. git apply既可以合入git diff文件又可以合入git format-patch文件,而git am只能合入git format-patch文件
  2. git apply不会自动commit,而git am会自动commit
转载自:https://juejin.cn/post/7068200484674207781
评论
请登录