若是你曾有機會在一個使用分佈式開發模型的大型代碼庫上工做過,你就應該據說過相似下面的話,「Sue 剛發過來一個補丁patch」,「Rajiv 正在簽出checking out差別diff」, 可能這些詞(補丁、差別文件)對你而言很陌生,而你肯定很想搞懂他們到底指什麼。開源軟件對上述提到的名詞有很大的貢獻,做爲大型項目從 Apache web 服務器到 Linux 內核的開發模型,「基於補丁文件的開發」 這一模式貫穿了上述項目的始終。實際上,你可能不知道 Apache 的名字就來自「一系列的代碼補丁」(LCTT 譯註:Apache 英文發音和補丁的英文 patch 類似),它們被一一收集起來並針對原來的 NCSA HTTPd server source code 進行了修訂。linux
你可能認爲這只不過是些逸聞,可是一份早期的 Apache 網站的存檔中 聲稱 Apache 的名字就是來自於最先的「補丁」集合;即「打了補丁的APAtCHy」服務器,簡化爲 Apache。程序員
好了,言歸正傳,程序員嘴裏說的「差別」和「補丁」究竟是什麼?web
首先,在這篇文章裏,咱們能夠認爲這兩個術語都指向同一個概念。「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 表明遞歸比較目錄)