git版本管理软件——git发布补丁和打补丁

一时失言乱红尘 2022-06-09 12:05 953阅读 0赞
  1. 某几个文件的代码修改后要发到同事开发的代码中,或者修复了bug后要将修复的代码添加到另外一份库中,这个时候手动记下改动太麻烦,git有创建补丁的功能,即将改动的代码统一添加到一个补丁文件中,后缀名为.patch,然后通过邮件或U盘的形式将补丁发送到需要的版本中,然后再执行打补丁命令,这样改动会自动合并到该版本库中。

git创建补丁git format-patch

git可以将修改过的差异打包成文件,以补丁的形式发布,补丁的后缀名为patch,创建的补丁保存在当前目录下。

1、通过git diff创建补丁

  1. 命令:git diff > my.patch

该命令最直接的是将diff不同的地方将其打包成补丁,以my.patch的文件将diff的内容保存下来,文件的内容如下所示

  1. diff --git a/reset.txt b/reset.txt
  2. index 7389186..53cef72 100644
  3. --- a/reset.txt
  4. +++ b/reset.txt
  5. @@ -1 +1,4 @@
  6. add reset
  7. +
  8. +add git patch test
  9. +
  10. 命令:git diff --no-prefix > my.patch

该命令与上一个命令不同的是,将对比文件前后的形象标志去掉了。

  1. diff --git reset.txt reset.txt
  2. index 7389186..53cef72 100644
  3. --- reset.txt
  4. +++ reset.txt
  5. @@ -1 +1,4 @@
  6. add reset
  7. +
  8. +add git patch test
  9. +
  10. 命令:git diff master > patch

与上面的命令相同,即将master上的改动打包成补丁。

2、通过某个提交创建补丁

具体将某一次的commit提交的内容和以后提交的commit的内容分别以文件分开,将改动封装成补丁。

  1. 命令:git format-patch <commit id>
  2. commit 99e826d211ddea11689d09e0362877c076522b13
  3. Author: zx <zx@git.com>
  4. Date: Sun Nov 6 20:54:33 2016 +0800
  5. add test git patch
  6. commit 1996afe5edeaab3f7269dcbe51f2d658936d7f8c
  7. Merge: 546d73a 0f58788
  8. Author: zx <zx@git.com>
  9. Date: Sun Nov 6 20:12:38 2016 +0800
  10. add readme
  11. commit 546d73a5842ecd4df8dc35994bc520b22c12fcb3
  12. Author: zx <zx@git.com>
  13. Date: Sun Nov 6 09:26:29 2016 +0800
  14. add reset.txt
  15. ghost@ghost-machine:~/workspace/test/Project_test$ git format-patch 546d73a5842ecd4df8dc35994bc520b22c12fcb3
  16. 0001-add-readme.txt.patch
  17. 0002-add-test-git-patch.patch
  18. ghost@ghost-machine:~/workspace/test/Project_test$ ls
  19. 0001-add-readme.txt.patch 0002-add-test-git-patch.patch readme.txt reset.txt
  20. ghost@ghost-machine:~/workspace/test/Project_test$

3、最近的commit提交的补丁

  1. 命令:git format-patch HEAD^ <==最近的1commitpatch
  2. 命令:git format-patch HEAD^^ <==最近的2commitpatch

与上面得到的结果一样,这样做就不用输入commit的哈希值

最终的补丁的内容为

  1. From 99e826d211ddea11689d09e0362877c076522b13 Mon Sep 17 00:00:00 2001
  2. From: zx <zx@git.com>
  3. Date: Sun, 6 Nov 2016 20:54:33 +0800
  4. Subject: [PATCH] add test git patch
  5. ---
  6. reset.txt | 3 +++
  7. 1 file changed, 3 insertions(+)
  8. diff --git a/reset.txt b/reset.txt
  9. index 7389186..53cef72 100644
  10. --- a/reset.txt
  11. +++ b/reset.txt
  12. @@ -1 +1,4 @@
  13. add reset
  14. +
  15. +add git patch test
  16. +
  17. --
  18. 2.7.4

git打补丁patch

将创建的补丁放在同一份镜像版本上,即开发过程中另外同事的开发版本上,输入打补丁命令:

  1. 命令:patch -p1 < my.patch
  2. 命令:patch -p0 < my.patch

p后面的数字0,1,2,是指略去的patch文件中的前几级目录,对于diff文件的内容来说

  1. diff --git a/reset.txt b/reset.txt
  2. index 7389186..53cef72 100644
  3. -p0 就表示从当前目录,找一个叫作b的目录再在这个目录中找一个reset.txt的文件。
  4. -p1 就表示从当前目录,忽略第一层b的目录,在当前目录中找一个reset.txt的文件。

当前目录可以用命令:pwd得到。

命令:patch -p1 < my.patch 效果显示为

  1. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ ls
  2. my.patch readme.txt reset.txt
  3. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ patch -p1 < my.patch
  4. patching file reset.txt
  5. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ git status
  6. 位于分支 master
  7. 您的分支与上游分支 'origin/master' 一致。
  8. 尚未暂存以备提交的变更:
  9. (使用 "git add <文件>..." 更新要提交的内容)
  10. (使用 "git checkout -- <文件>..." 丢弃工作区的改动)
  11. 修改: reset.txt
  12. 未跟踪的文件:
  13. (使用 "git add <文件>..." 以包含要提交的内容)
  14. my.patch
  15. 修改尚未加入提交(使用 "git add" 和/或 "git commit -a"
  16. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$

对于命令:git diff —no-prefix > my.patch所创建的补丁来说

  1. diff --git reset.txt reset.txt
  2. index 7389186..53cef72 100644

命令:patch -p0 < my.patch 效果显示为

  1. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ ls
  2. my.patch readme.txt reset.txt
  3. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ patch -p0 < my.patch
  4. patching file reset.txt
  5. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ git status
  6. 位于分支 master
  7. 您的分支与上游分支 'origin/master' 一致。
  8. 尚未暂存以备提交的变更:
  9. (使用 "git add <文件>..." 更新要提交的内容)
  10. (使用 "git checkout -- <文件>..." 丢弃工作区的改动)
  11. 修改: reset.txt
  12. 未跟踪的文件:
  13. (使用 "git add <文件>..." 以包含要提交的内容)
  14. my.patch
  15. 修改尚未加入提交(使用 "git add" 和/或 "git commit -a"
  16. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$

对于命令:git format-patch所创建的补丁,打补丁后不会将原来的commit的信息打上去,也就是打补丁后git log看不到commit的信息,而是以差异化的形式将补丁打上去,用git diff可以看到,打完补丁后还需要手动git add 和git commit提交自己的修改。

如果此时再打补丁,git会有明显的提示,提示该补丁已经打过,会询问下一步,如下所示,输入n是不变,输入y为还原该补丁的改动

  1. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ patch -p1 < my.patch
  2. patching file patch.txt
  3. Reversed (or previously applied) patch detected! Assume -R? [n]

效果如下所示

  1. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ patch -p1 < 0001-add-test-git-patch.patch
  2. patching file reset.txt
  3. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ git log
  4. commit 1996afe5edeaab3f7269dcbe51f2d658936d7f8c
  5. Merge: 546d73a 0f58788
  6. Author: zx <zx@git.com>
  7. Date: Sun Nov 6 20:12:38 2016 +0800
  8. add readme
  9. commit 546d73a5842ecd4df8dc35994bc520b22c12fcb3
  10. Author: zx <zx@git.com>
  11. Date: Sun Nov 6 09:26:29 2016 +0800
  12. add reset.txt
  13. commit 70456a99ee3899c40d4846b7101646855b7a1219
  14. Author: zx <zx@git.com>
  15. Date: Tue Jun 14 22:55:17 2016 +0800
  16. add 20160614.
  17. commit 824005a2c174d195c5823b2a412ce2c3081c39f3
  18. Author: zx <zx@git.com>
  19. Date: Tue Jun 14 22:53:50 2016 +0800
  20. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$ git diff
  21. diff --git a/reset.txt b/reset.txt
  22. index 7389186..53cef72 100644
  23. --- a/reset.txt
  24. +++ b/reset.txt
  25. @@ -1 +1,4 @@
  26. add reset
  27. +
  28. +add git patch test
  29. +
  30. ghost@ghost-machine:~/workspace/test/ghost_project/Project_test$

git撤销打补丁

撤销该补丁的修改效果回到打补丁前代码的状态

  1. 命令:patch -R -p1 < my.patch

撤销补丁还有种更方便的方法,将文件还原checkout,但这个是对文件整体的还原,该文件除补丁之外的修改也被还原了。

#打补丁或pull仓库造成的冲突解决
冲突是指打补丁或拉远程仓库的内容和工作版本修改的同一个地方不一致,补丁修改或远程仓库的改动的地方的原型与本地工作版本修改的地方不一致。

例如git pull时会有如下提示

  1. 来自 /home/ghost/warehouse/Project_test
  2. 155169b..d8b74f0 master -> origin/master
  3. 自动合并 patch.txt
  4. 冲突(内容):合并冲突于 patch.txt
  5. 自动合并失败,修正冲突然后提交修正的结果。

形成冲突的文本文件如下所示

  1. patch diff test
  2. <<<<<<< HEAD
  3. patch diff is 2
  4. =======
  5. patch diff is 1
  6. >>>>>>> d8b74f02ffdf6b2843fdce848490d40f6e562c95

<<<<<<< HEAD到=======,这个范围内的内容为本地文件的内容。
=======到>>>>>>> d8b74f02ffdf6b2843fdce848490d40f6e562c95,这个范围内的内容是哈希值d8b74f0xxx的commit提交所修改的内容,这两个地方修改的内容不一致,这就需要手动去修改。

手动修改,将代码保留最新的结果,手动删除冲突提示,修改的结果如下

  1. patch diff test
  2. patch diff is 2

修改后再git add 、git commit,添加注释说明解决冲突的原因。
如果是打补丁,打完补丁后记得要将补丁删除,以免将补丁加入到版本管理中。

打补丁或pull仓库造成的冲突解决

冲突是指打补丁或拉远程仓库的内容和工作版本修改的同一个地方不一致,补丁修改或远程仓库的改动的地方的原型与本地工作版本修改的地方不一致。
例如git pull时会有如下提示

  1. 来自 /home/ghost/warehouse/Project_test
  2. 155169b..d8b74f0 master -> origin/master
  3. 自动合并 patch.txt
  4. 冲突(内容):合并冲突于 patch.txt
  5. 自动合并失败,修正冲突然后提交修正的结果。

形成冲突的文本文件如下所示

  1. patch diff test
  2. <<<<<<< HEAD
  3. patch diff is 2
  4. =======
  5. patch diff is 1
  6. >>>>>>> d8b74f02ffdf6b2843fdce848490d40f6e562c95

**<<<<<<< HEAD到=======,这个范围内的内容为本地文件的内容。
**=======到>>>>>>>
d8b74f02ffdf6b2843fdce848490d40f6e562c95,这个范围内的内容是哈希值d8b74f0xxx的commit提交所修改的内容,这两个地方修改的内容不一致,这就需要手动去修改。

手动修改,将代码保留最新的结果,手动删除冲突提示,修改的结果如下

  1. patch diff test
  2. patch diff is 2

修改后再git add 、git commit,添加注释说明解决冲突的原因。
如果是打补丁,打完补丁后记得要将补丁删除,以免将补丁加入到版本管理中。

发表评论

表情:
评论列表 (有 0 条评论,953人围观)

还没有评论,来说两句吧...

相关阅读

    相关 为什么开源软件补丁很难

    对于数据中心运营商来说,开源软件提供了许多优势。它是免费的软件,其代码可以被检查和修改。此外,如果是一个流行的软件包,那么可能还拥有一个庞大的包含支持论坛、相关工具、兼容

    相关 diffpatch 补丁

    在Linux环境下,有两个工具用来给project打补丁,即diff和patch diff          diff具有比较功能。可以使用man命令查看其使

    相关 Git 补丁patch

    补丁patch 补丁并不是针对所有代码的修改,只是针对于局部的修改。 在代码的维护中,如果只修改一部分代码,需要将代码完整的克隆下来,可是修改的只是很小的一部分;在这