1:前言

在合作开发领域中,不得不说git这一个版本控制工具是最伟大的发明,在项目开发中已经是IT人必不可少的工具。但是如何给已有项目打补丁,如何在线上运行的项目做增量修改是运维以及开发者需要掌握的一个比较高级的git技术,本文也是笔者自学以及踩坑后才有所心得,如有误区,望读者斧正。

2:背景介绍

近期发现线上有一个bug需要修复,需要紧急上线,因为改动很小,无需整包替换,所以决定采取线上打patch的方式实现修复,因此需要线下根据最新的commit打一个线上对应版本的patch文件,然后将这个patch文件上传到线上,实现打补丁修复。

3:步骤:

(1)在本地创建线上的项目版本的分支

执行以下代码确保补丁分支和线上代码保持一致,这里stable是线上运行的代码的分支名(注意不能完全照抄,依据实际情况自行修改

git  fetch
git checkout -b fix_sg origin/stable

保证打的patch是基于线上项目的基准上的,否则可能会产生冲突以及其他不可预知后果。

(2)检查当前patch分支工作区

检查当前分支工作区干净整洁。

$ git status
On branch fix_sg
Your branch is up-to-date with 'origin/stable'.
nothing to commit, working tree clean

(3)修改线上问题的bug后再检查工作区

$ git status
On branch fix_sg
Your branch is up-to-date with 'origin/stable'.
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:   test/services/agents/redis.pyno changes added to commit (use "git add" and/or "git commit -a")

如上所示,要确保只修改了自己想要修改的文件

(4)git commit提交代码

这个不用多说git add + git commit的基础操作。

(5)是否需要git push?

如果,当前的patch修改需要同步到其他所有该项目的分支中,就需要git push到远程,在远程创建一个分支,待日后进行merge或者rebase等其他操作,如果暂时不需要对代码库中其他的分支做操作,可以暂时不需要push,可能下次升级代码会已经修复。笔者这里因为某些原因,这里暂不push,因为不push也可以打patch。

(6)查看commit日志。并给予commit_id生成patch文件

查看提交日志,确保最上层的是自己刚刚第(4)步提交的代码。(笔者对下面数据做了一部分脱敏操作)

$ git log
commit 2ff7887def36438a399c8a1df7265e
Date:   Fri Sep 23 21:32:32 2022 +0800bugfix for sgcommit 794f9eea2fedcccc822326e8cef2f1f
Date:   Tue Sep 20 15:26:19 2022 +0800Bugfix delete routeFix 'varp_ip' is not defined.

二级果发现最上层的正好是当前最新的提交,且第二层和线上的代码最新的提交也一致,接下来执行如下代码,将最新的提交打成patch文件。

git format-patch + commit ID

执行效果如下

$ git format-patch 794f9eea2fedcccc822326e8cef2f1f
0001-bugfix-for-sg.patch

这里需要注意的是,打patch文件使用的这个format-patch指令是开区间,即如果你想要只打刚刚的提交代码为patch,那么后面的commit ID一定是最新的提交之前的一个commit ID。

(7)查看patch文件

执行完(6),在当前的目录下会出现一个0001-bugfix-for-sg.patch的补丁文件。

(8)将该补丁文件上传到线上,并准备打patch

如何上传patch文件这里不再赘述,可以参考笔者这篇文章:https://blog.csdn.net/qq_21583139/article/details/119588733
当然,公司都是由运维负责的,会有其他的运维分发工具这里就不多说了。
正式打patch前,一定要先备份原项目代码,一定要备份,一定要备份!!!
将patch文件放到线上项目目录下(有git工具)查看线上的当前最新commit,确保和打patch时fromat-patch后的是同一个id。
执行以下代码,功能是检查patch文件是否和项目冲突

git apply --check 0001-bugfix-for-sg.patch

注意:这里在执行检查冲突时会有可能产生冲突的,例如该项目中已有他人对同行代码做过更改等导致线上项目代码不干净,此时需要手动介入解决冲突,解决完冲突执行

git am --continue

表示继续,此时再次执行检查冲突指令,当此时执行后,控制台没有任何输出,说明没有冲突,可以打patch,执行

git am 0001-bugfix-for-sg.patch

注意,这个步骤还是有可能报错的,例如之前曾经在这个项目中打过其他的patch,但是某种原因使得这个patch没有打成功,此时再打新的patch会提示如下报错

previous rebase directory /opt/project/.git/rebase-apply still exists but mbox given.

此时有两种解决方法:

(1)直接git am --skip

使用这个方法是有风险的,首先要确保当前的线上代码包是刚更新不久的,且每次升级都是安装包全量替换的,否则可能其他人没有打完的patch会被你跳过,因此需要确保上个失败的patch的作者的意图。当然,直接skip掉后,一定会成功打patch成功。

(2)执行git am --abort

执行这个方法,一般是在征求了上个patch的作者同意后,上一个patch是失败了,但是必须也要打入这个项目中,那么执行这个语句就会回到上一个打的这个patch的环境下,对上一次失败的patch进行处理(注意:执行这个方法可能这个旧的patch的分支很旧,和自己要打的patch的分支相差多个版本,如果可以的话,推荐方法(1)
在具体执行上述两种解决方案前,我们不妨看看上个失败的patch目录下的内容,进入这个目录下,
发现这个目录下内容如下

[root@ rebase-apply]# ll
total 68
-rw-r--r-- 1 root root 1086 Sep 21 23:22 0001
-rw-r--r-- 1 root root    0 Sep 21 23:22 applying
-rw-r--r-- 1 root root    2 Sep 21 23:22 apply-opt
-rw-r--r-- 1 root root   54 Sep 21 23:22 final-commit
-rw-r--r-- 1 root root  121 Sep 21 23:22 info
-rw-r--r-- 1 root root    1 Sep 21 23:22 keep
-rw-r--r-- 1 root root    1 Sep 21 23:22 keepcr
-rw-r--r-- 1 root root    2 Sep 21 23:22 last
-rw-r--r-- 1 root root   30 Sep 21 23:22 msg
-rw-r--r-- 1 root root   54 Sep 21 23:22 msg-clean
-rw-r--r-- 1 root root    2 Sep 21 23:22 next
-rw-r--r-- 1 root root    1 Sep 21 23:22 no_inbody_headers
-rw-r--r-- 1 root root  863 Sep 21 23:22 patch    《-----------上一个失败的patch文件
-rw-r--r-- 1 root root    1 Sep 21 23:22 quiet
-rw-r--r-- 1 root root    1 Sep 21 23:22 scissors
-rw-r--r-- 1 root root    1 Sep 21 23:22 sign
-rw-r--r-- 1 root root    1 Sep 21 23:22 threeway
-rw-r--r-- 1 root root    2 Sep 21 23:22 utf8

这里是可以vim patch看见上一个patch的内容的。
这里我继续执行git am --abort,注意事项见上面,结果如下

[root project]# git am --abort
Unstaged changes after reset:
M       etc/test.conf

因为git am --abort是回退到上一个patch打错的场景,清空所有patch缓存,此时再去查看上述的缓存的patch目录已经不在了。值得注意的是,可能会回退当前项目版本,所以谨慎起见,检查一下commit 提交记录,执行git log对比,结果发现提交记录和线下的一致,只相差了最新的patch记录,此时再次执行如下

git apply --check 0001-bugfix-for-sg.patch
git am 0001-bugfix-for-sg.patch

结果如下:说明打patch成功

[root  project]# git am 0001-bugfix-for-sg.patch
Applying: bugfix for sg

(9)打完patch后,执行运维剩下的操作,安装,编译,重启等操作即可

4:注意事项

本文所列:
(1)使用git format-patch时,后面的commit id是个‘开区间’取值,如果想要打某两个commit间所有的patch,那就更要注意。
(2)git am --abort 和git am --skip孰优孰劣无法评估,需要依照实际情况而定
(3)打patch前一定要先备份项目,一旦使用了–abort或者–skip产生未预料的情况,及时回滚,以便后续整包替换或者部分代码文件替换这些替代方案。
(4)多个服务同时打同一个patch,会新生成同一个commit_id,如果这些服务不是同一时间打的patch,那么每次打的patch都会在当前的服务中随机hash生成一个新的commit_id,因此,在运维操作中,千万不要以新的patch的commit_id为唯一依据

git项目如何打patch以及打patch的注意事项相关推荐

  1. git补丁操作:git生成patch和应用patch

    一.生成patch 1.拉取代码仓 git clone xxx代码仓地址 2.在clone到本地的代码目录中,例如对README.md文件进行了修改.然后使用 git status 命令查看工作目录和 ...

  2. 使用Git生成patch和应用patch

    1. 在git源码目录下执行 git format-patch <old_sha>...<new_sha> -o <patch_dir> 如 git format- ...

  3. git 生成多个patch_如何用git命令生成Patch和打Patch

    在程序员的日常开发与合作过程中,对于code的生成patch和打patch(应用patch)成为经常需要做的事情.什么是patch?简单来讲,patch中存储的是你对代码的修改,生成patch就是记录 ...

  4. [git 基础] 生成patch 和 打patch 的实例

    简洁点啊,我看 网上 很多搞得很复杂的介绍, 然后,最关键,他们 这边版本不仅抄来抄去,而且,还是一个英文 谷歌网页翻译版本. 搞得好复杂, 还没讲 清楚. 1生成Patch 直接就是在GUI上,选一 ...

  5. Git生成patch及打patch到源代码

    1.每个commit生成1个patch 1.1.创建patch 文件的常用命令行 1.1.1.某次提交(含)之前的几次提交 git format-patch [commitid] -n n 表示从指定 ...

  6. 如何用git命令生成Patch和打Patch(git format-Patch和git am)

    在程序员的日常开发与合作过程中,对于code的生成patch和打patch(应用patch)成为经常需要做的事情. 什么是patch?简单来讲,patch中存储的是你对代码的修改 什么是生成patch ...

  7. git 生成patch和打patch的方法

    主要还是为了记住一些命令 git format-patch HEAD^ 成功之后会在当前目录生成一个*.patch文件 打patch的时候需要执行git am xxx.patch 这是patch打成功 ...

  8. git生成patch和打patch

    日常开发与合作过程中,对于code生成patch和打patch(应用patch)成为经常需要做的事情,使用方法(直接给出一些examples): 生成patch git diff > xxx.p ...

  9. git项目创建、克隆(基于git bash)

    git项目创建.克隆(基于git bash) 1.本地搭建仓库 1)先在远程仓库(gitee)创建项目 2)在本地打开git bash用下面的代码初始化 3) 给本地仓库添加远程仓库 4) 配置.gi ...

最新文章

  1. ValueError: urls must start with a leading slash
  2. 二、前端开发-HTML
  3. 模板模式与策略模式/template模式与strategy模式/行为型模式
  4. mysql数据库学习——2,数据库的选定,创建,删除和变更
  5. HTML+CSS零基础学习笔记(二)
  6. Nmap (网络扫描工具)
  7. 【H5调用iOS原生高德定位】
  8. ERP原理与应用教程-第一章
  9. 软件测试工程师工作总结
  10. android 本地存储数组,安卓与iphone自带浏览器对本地存储的支持
  11. CocosCreator 子弹运动轨迹的绘制
  12. Git Branching
  13. git最佳实践之feature和hotfix分支
  14. 从一个运维人员的角度看微盟的这次删库跑路的节奏
  15. vue 实现级联选择器
  16. win7查看网络连接属性报错:网络连接出现意外错误
  17. python rgb转hsv_使用Python / PIL检测HSV颜色空间(来自RGB)的阈...
  18. 50页PPT|智能工厂总体规划及实施指南
  19. 数学文化 蒲丰投针
  20. 【MSD6A648】VSYNC_LIKE和PWM2冲突

热门文章

  1. Python机器学习/数据挖掘项目实战 波士顿房价预测 回归分析
  2. 【乐绘派】Audition专业音频后期制作教程 | 5-自定义工作区
  3. C++string常用函数用法解析
  4. Chrome自签名证书配置
  5. Dispatch Source Timer
  6. html中重复复制一行快捷键,剪切、拷贝、粘贴和其他常用快捷键
  7. c语言变大变小的图片,51单片机模拟水滴由小变大然后滴落现象(附带C语言源码)...
  8. 用OpenVINO工具包轻松实现PP-OCR实时推理
  9. MySQL导出数据库、数据库表结构、存储过程及函数【用】
  10. LearnOpenGL 光照—材质