0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

”差异“和”补丁“是什么?怎么使用命令行工具和它们交互?

Linux爱好者 来源:未知 作者:李倩 2018-10-04 16:05 次阅读

如果你曾有机会在一个使用分布式开发模型的大型代码库上工作过,你就应该听说过类似下面的话,“Sue 刚发过来一个补丁patch”,“Rajiv 正在签出checking out差异diff”, 可能这些词(补丁、差异文件)对你而言很陌生,而你确定很想搞懂他们到底指什么。开源软件对上述提到的名词有很大的贡献,作为大型项目从 Apache web 服务器到 Linux 内核的开发模型,“基于补丁文件的开发” 这一模式贯穿了上述项目的始终。实际上,你可能不知道 Apache 的名字就来自“一系列的代码补丁”(LCTT 译注:Apache 英文发音和补丁的英文 patch 相似),它们被一一收集起来并针对原来的NCSA HTTPd server source code进行了修订。

你可能认为这只不过是些逸闻,但是一份早期的Apache 网站的存档中声称 Apache 的名字就是来自于最早的“补丁”集合;即“打了补丁的APAtCHy”服务器,简化为 Apache。

好了,言归正传,程序员嘴里说的“差异”和“补丁”到底是什么?

首先,在这篇文章里,我们可以认为这两个术语都指向同一个概念。“diff” 是 ”difference“ 的简写;Unix 下的同名工具程序diff剖析了一个或多个文件之间的“差异”。下面我们会看到diff的例子:

一个“补丁”指的是文件之间一系列差异,这些差异能被 Unix 的diff程序应用在源代码树上。我们能使用diff工具来创建“差异”(或“补丁”),然后使用该工具将它们 “打” 在一个没有这个补丁的同样的源代码版本上。此外,(我又要开始跑题说些历史轶事了……),“补丁” 这个词真的指在计算机的早期使用打卡机的时候,用来覆盖在打孔纸带上来对软件进行修改的覆盖纸,那个时代打孔纸带就是在计算机处理器上运行的程序。下面来自维基页面的这张图真切的描绘了最初的“打补丁”这个词的出处:

现在你对补丁和差异就了一个基本的概念,让我们来看看软件开发者是怎么使用这些工具的。如果你还没有使用过类似于Git或subversion这样的源代码版本控制工具的话,我将会一步步展示最流行的软件项目是怎么使用它们的。如果你将一个软件的生命周期看成是一条时间线的话,你就能看见这个软件的点滴变化,比如在何时源代码加上了一个功能,在何时源代码修复了一个功能缺陷。我们称这些改变的点为“提交commit”,“提交”这个词被当今最流行的源代码版本管理工具 Git 所使用,当你想检查在一个提交前后的代码变化的话,(或者在许多个提交之间的代码变化),你都可以使用工具来观察文件差异。

如果你同样在使用 Git 开发软件的话,你可以在你的本地开发环境做些希望交给别的开发者的提交,以添加到他们的源代码树中。为了给别的开发者你的提交,一个方法就是创建一个你本地文件的差异文件,然后将这个“补丁”发送给和你工作在同一个源代码树的别的开发者。别的开发者在“打”了你的补丁之后,就能看到在你的代码变树上的变化。

Linux、Git 和 GitHub

这种分享补丁的开发模型正是现今 Linux 内核社区如何处理内核修改提议而采用的模型。如果你有机会浏览任何一个主流的 Linux 内核邮件列表 —— 主要是LKML,也包括linux-containers、fs-devel、Netdev等等,你能看到很多开发者会贴出他们想让其他内核开发者审核、测试或者合入 Linux 官方 Git 代码树某个位置的补丁。当然,讨论 Git 不在这篇文章范围之内(Git 是由 Linus Torvalds 开发的源代码控制系统,它支持分布式开发模型以及允许独立于主要代码仓库的补丁包,这些补丁包能被推送或拉取到不同的源代码树上,并遵守这些代码树各自的开发流程。)

在继续我们的话题之前,我们当然不能忽略和补丁和差异这个概念相关的最流行的服务:GitHub。从它的名字就能猜想出 GitHub 是基于 Git 的,而且它还围绕着 Git 对分布式开源代码开发模型提供了基于 Web 和 API 的工作流管理。(LCTT 译注:即拉取请求Pull Request)。在 GitHub 上,分享补丁的方式不是像 Linux 内核社区那样通过邮件列表,而是通过创建一个拉取请求。当你提交你自己的源代码树的改动时,你能通过创建一个针对软件项目的共享仓库的“拉取请求”来分享你的代码改动(LCTT 译注:即核心开发者维护一个主仓库,开发者去“复刻fork”这个仓库,待各自的提交后再创建针对这个主仓库的拉取请求,所有的拉取请求由主仓库的核心开发者批准后才能合入主代码库。)GitHub 被当今很多活跃的开源社区所采用,如Kubernetes、Docker、容器网络接口 (CNI)、Istio等等。在 GitHub 的世界里,用户会倾向于使用基于 Web 页面的方式来审核一个拉取请求里的补丁或差异,你也可以直接访问原始的补丁并在命令行上直接使用它们。

该说点干货了

我们前面已经讲了在流行的开源社区里是怎么应用补丁和差异的,现在看看一些例子。

第一个例子包括一个源代码树的两个不同副本,其中一个有代码改动,我们想用diff来看看这些改动是什么。这个例子里,我们想看的是“合并格式unified”的补丁,这是现在软件开发世界里最通用的格式。如果想知道更详细参数的用法以及如何生成差异文件,请参考diff手册。原始的代码在sources-orig目录,而改动后的代码在sources-fixed目录。如果要在你的命令行上用“合并格式”来展示补丁,请运行如下命令。(LCTT 译注:参数-N代表如果比较的文件不存在,则认为是个空文件,-a代表将所有文件都作为文本文件对待,-u代表使用合并格式并输出上下文,-r代表递归比较目录)

$ diff -Naur sources-orig/ sources-fixed/

……下面是 diff 命令的输出:

最开始几行 diff 命令的输出可以这样解释:三个 --- 显示了原来文件的名字;任何在原文件(LCTT 译注:不是源文件)里存在而在新文件里不存在的行将会用前缀 -,用来表示这些行被从源代码里“减去”了。而 +++ 表示的则相反:在新文件里被加上的行会被放上前缀 +,表示这是在新文件里被“加上”的行。补丁文件中的每一个补丁“块”(用 @@ 作为前缀的的部分)都有上下文的行号,这能帮助补丁工具(或其它处理器)知道在代码的哪里应用这个补丁块。你能看到我们已经修改了“Office Space”这部电影里提到的那个函数(移除了三行并加上了一行代码注释),电影里那个有点贪心的工程师可是偷偷的在计算利息的函数里加了点“料”哦。(LCTT译注:剧情详情请见电影 https://movie.douban.com/subject/1296424/)

如果你想找人来测试你的代码改动,你可以将差异保存到一个补丁里:

$ diff -Naur sources-orig/ sources-fixed/ >myfixes.patch

现在你有补丁 myfixes.patch 了,你能把它分享给别的开发者,他们可以将这个补丁打在他们自己的源代码树上从而得到和你一样的代码并测试他们。如果一个开发者的当前工作目录就是他的源代码树的根的话,他可以用下面的命令来打补丁:

$patch -p1 < ../myfixes.patch

patching file officespace/interest.go

现在这个开发者的源代码树已经打好补丁并准备好构建和测试文件的修改了。那么如果这个开发者在打补丁之前已经改动过了怎么办?只要这些改动没有直接冲突(LCTT 译注:比如改在同一行上),补丁工具就能自动的合并代码的改动。例如下面的interest.go 文件,它有其它几处改动,然后它想打上 myfixes.patch 这个补丁:

$patch -p1 < ../myfixes.patch

patching file officespace/interest.go

Hunk#1 succeeded at 26 (offset 15 lines).

在这个例子中,补丁警告说代码改动并不在文件原来的地方而是偏移了 15 行。如果你文件改动的很厉害,补丁可能干脆说找不到要应用的地方,还好补丁程序提供了提供了打开“模糊”匹配的选项(这个选项在文档里有预置的警告信息,对其讲解已经超出了本文的范围)。

如果你使用 Git 或者 GitHub 的话,你可能不会直接使用补丁或差异。Git 已经内置了这些功能,你能使用这些功能和共享一个源代码树的其他开发者交互,拉取或合并代码。Git 一个比较相近的功能是可以使用 git diff 来对你的本地代码树生成全局差异,又或者对你的任意两次”引用“(可能是一个代表提交的数字,或一个标记或分支的名字,等等)做全局补丁。你甚至能简单的用管道将 git diff 的输出到一个文件里(这个文件必须严格符合将要被使用它的程序的输入要求),然后将这个文件交给一个并不使用 Git 的开发者应用到他的代码上。当然,GitHub 把这些功能放到了 Web 上,你能直接在 Web 页面上查看一个拉取请求的文件变动。在 Web 上你能看到所展示的合并差异,GitHub 还允许你将这些代码改动下载为原始的补丁文件。

总结

好了,你已经学到了”差异“和”补丁“是什么,以及在 Unix/Linux 上怎么使用命令行工具和它们交互。除非你还在像 Linux 内核开发这样的项目中工作而使用完全基于补丁文件的开发方式,你应该会主要通过你的源代码控制系统(如 Git)来使用补丁。但熟悉像 GitHub 这样的高级别工具的技术背景和技术底层对你的工作也是大有裨益的。谁知道会不会有一天你需要和一个来自 Linux 世界邮件列表的补丁包打交道呢?

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10988

    浏览量

    206726
  • 服务器
    +关注

    关注

    12

    文章

    8113

    浏览量

    82499
  • 源代码
    +关注

    关注

    94

    文章

    2926

    浏览量

    66061

原文标题:差异文件(diff)和补丁文件(patch)简介

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    在STM32实现命令行

    工作中的开发环境都是基于linux命令行交互,作为命令行的重度使用者,玩单片机也要使用命令行工具,百度了一些
    发表于 12-09 11:32 1623次阅读

    Linux命令行工具

    Linux 新手往往对命令行心存畏惧。部分原因是因为需要记忆大量的命令,毕竟掌握命令是高效使用命令行的前提不幸的是,学习这些命令并无捷径,
    发表于 07-25 08:10

    为什么需要使用命令行调试程序?

    为什么需要使用命令行调试程序?通过嵌入式开发中通过命令行调试程序的过程是怎样的?
    发表于 12-24 06:44

    openssl无法使用命令行生成CMAC怎么解决?

    我正在尝试生成应用程序代码的离线 CMAC 以实现安全启动。我曾尝试使用 openssl,但无法使用命令行生成 CMAC。是否有任何工具可以生成应用程序代码的 CMAC 和签名。我还研究了信任链文档 AN4235,但没有帮助。
    发表于 03-30 06:35

    Xilinx软件命令行工具:XSCT开发和调试

    了解如何使用XSCT,Xilinx软件命令行工具进行开发和调试。 该视频演示了XSCT如何充当Xilinx SDK的命令行控制台。
    的头像 发表于 11-21 06:02 1.3w次阅读

    Xilinx软件命令行工具进行开发和调试

    了解如何使用XSCT,Xilinx软件命令行工具进行开发和调试。 该视频演示了XSCT如何充当Xilinx SDK的命令行控制台。
    的头像 发表于 11-22 06:53 6086次阅读

    维基链的命令行是如何高效快速的对维基链节点进行操作的

    命令行,是一种面向开发者的工具。 众所周知,在Linux系统中,Linux本身也提供了一系列的命令行工具,比如ls、cd、ps等等开发者常用命令
    发表于 06-24 11:15 870次阅读

    Golang基于flag库实现一个命令行工具

    Golang 标准库中的 flag 库提供了解析命令行选项的能力,我们可以基于此来开发命令行工具
    的头像 发表于 10-28 09:26 975次阅读

    新的开源命令行工具west

    电子发烧友网站提供《新的开源命令行工具west.zip》资料免费下载
    发表于 11-11 09:25 0次下载
    新的开源<b class='flag-5'>命令行</b><b class='flag-5'>工具</b>west

    如何使用命令行在Linux中查找文件?

    终端,命令行提供了几个用于搜索文件的工具,包括查找、定位、grep 和 where is,仅举几例。 那么如何使用命令行在Linux中查找文件?在Linux中查找文件的12 种方法: 1、查找
    的头像 发表于 03-23 14:55 2442次阅读

    一个开源MCU级的命令行交互组件

    一个开源MCU级命令行交互组件~
    的头像 发表于 10-17 16:26 190次阅读
    一个开源MCU级的<b class='flag-5'>命令行</b><b class='flag-5'>交互</b>组件

    用命令行工具ADB(Android Debug Bridge)常见的ADB命令

    ADB(Android Debug Bridge)是一种通用命令行工具,可以让您通过计算机与设备通信。
    的头像 发表于 11-05 11:26 403次阅读

    pycharm命令行终端运行代码

    Python是一种非常流行的编程语言,许多开发者使用它来编写各种应用程序和脚本。为了方便开发者编写和测试代码,PyCharm是一种集成开发环境(IDE),它提供了许多功能和工具,其中包括命令行终端
    的头像 发表于 11-22 11:20 1335次阅读

    eclipse怎么使用命令行

    命令行中使用Eclipse来完成一些特定的任务。本文将详细介绍如何在命令行中使用Eclipse。 首先,我们需要确保已经正确安装了JDK(Java Development Kit)和Eclipse
    的头像 发表于 12-06 11:26 928次阅读

    HarmonyOS开发:【基于命令行(安装库和工具集)】

    使用命令行进行设备开发时,可以通过以下步骤安装编译OpenHarmony需要的库和工具
    的头像 发表于 04-25 21:03 10次阅读
    HarmonyOS开发:【基于<b class='flag-5'>命令行</b>(安装库和<b class='flag-5'>工具</b>集)】