首頁  >  文章  >  php教程  >  Git的Patch功能

Git的Patch功能

黄舟
黄舟原創
2016-12-13 14:16:441307瀏覽

普通開發者從軟體倉庫clone下程式碼,然後寫入程式碼,做一個Patch, 最後用E-mail寄給Linux Kernel的維護者就好了。 Git最初作為Linux的版本控制工具,提供了透明、完整、穩定的Patch功能。

我們先介紹一下Patch是什麼。如果一個軟體有了新版本,我們可以完整地下載新版本的程式碼進行編譯安裝。然而,像Linux Kernel這樣的大型項目,程式碼即使壓縮,也超過70MB,每次全新下載是有相當大的代價的。然而,每次更新變動的程式碼可能不超過1MB,因此,我們只 要能夠有兩個版本代碼的diff的數據,應該就可以以極低的代價更新程式了。因此,Larry Wall開發了一個工具:patch。它可以根據一個diff檔案進行版本更新。

不過在git中,我們沒有必要直接使用diff和patch來做補丁,這樣做既危險又麻煩。 git提供了兩種簡單的patch方案。一是用git diff產生的標準patch,二是git format-patch產生的Git專用Patch。

1.git diff產生的標準patch

我們可以先用git diff製作一個patch。本文範例的工作目錄裡最初有一個檔案a,內容是「This is the file a.”,放置在master分支。為了修改程式碼,我們一般的做法是建立一個新分支:

sweetdum@sweetdum-ASUS:~/GitEx$ git branch Fix
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout Fix
Switched to branch 'Fix'

接下來我們在a檔案裡面追加一行,然後執行git diff。
sweetdum@sweetdum-ASUS:~/GitEx$ echo 'Fix!!!'>>a
sweetdum@sweetdum-ASUS:~/GitEx$ git diff
diff --git a/a b/a
index 4add65f..0d295ac 100644
--- a/a
+++ b/a
@@ -1 +1,2 @@
This is the file a.
+Fix!!!

我們看到了Git diff的輸出,這是一個非常典型的Patch式diff。這樣我們可以直接把這個輸出變成一個Patch:
sweetdum@sweetdum-ASUS:~/GitEx$ git commit -a -m "Fix"
[Fix b88c46b] Fix
1 files changed, 1 insertions(+), 0 deletions(-)
sweetdum@sweetdum-ASUS:~/GitEx$ git diff master > patch
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout master
Switched to branch 'master'

我們現在有一個patch文件,並且簽出了master,接下來我們可以使用git apply來應用這個patch。當然了,實際應用中,我們不會這樣在一個分支建patch,到另一個分支去應用,因為只有merge一下就好了。我們現 在權當沒有這個Fix分支。一般情況下,為了保護master,我們會建立一個專門處理新交來的patch的分支:

sweetdum@sweetdum-ASUS:~/GitEx$ git branch PATCH
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout PATCH
Switched to branch 'PATCH'
sweetdum@sweetdum-ASUS:~/GitEx$ git apply patch
sweetdum@sweetdum-ASUS:~/GitEx$ git commit -a -m "Patch Apply"
[PATCH 9740af8] Patch Apply
1 files changed, 1 insertions(+), 0 deletions(-)

看,現在我們在PATCH分支中應用了這個補丁,我們可以把PATCH分支和Fix比對一下,結果肯定是什麼也沒有,說明PATCH分支和Fix分支完全一樣。 patch應用成功。即使有多個檔案git diff 也能產生一個patch。

2.git format-patch產生的git專用補丁。

我們同樣用上面那個例子的工作目錄,這次,我們在Fix分支中的a添加了新行之後,用git format-patch產生一個patch。
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout Fix
Switched to branch 'Fix'
sweetdum@sweetdum-ASUS:~/GitEx$ echo 'Fix!!!'>>a
sweetdum@sweetdum-ASUS:~/GitEx$ git commit -a -m "Fix1"
[Fix 6991743] Fix1
1 files changed, 1 insertions(+), 0 deletions(-)
sweetdum@sweetdum-ASUS:~/GitEx$ git format-patch -M master
0001-Fix1.patch

git format-patch的-M選項表示這個patch要跟那個分支比對。現在它產生了一個patch文件,我們看看那是什麼:

sweetdum@sweetdum-ASUS:~/GitEx$ cat 0001-Fix1.patch
From 6991743354857c9a6909a253e859e886165b0d90 Mon Sep 17 00:00:00 2001
From: Sweetdumplings
Date: Mon, 29 Aug 2011 14:06:12 +0800
Subject: [PATCH] Fix1

---
a |    1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diffgit/a. .0d295ac 100644
--- a/a
+++ b/a
@@ -1 +1,2 @@
This is the file a.
+Fix!!!
--
1.7.4.1

看,這次多了很多東西,不僅有diff的信息,還有提交者,時間等等,仔細一看你會發現,這是E-mail的文件,你可以直接發送它!這種patch,我們要用git am來應用。

sweetdum@sweetdum-ASUS:~/GitEx$ git checkout master
Switched to branch 'master'
sweetdum@sweetdum-ASUS:~/GitEx$ git branch PATCH
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout PATCH
sweetdum@sweetdum-ASUS:~/GitEx$ git am 0001-Fix1.patch
Applying: Fix1
sweetdum@sweetdum-ASUS:~/GitEx$ git commit -a -m "PATCH apply"

在提交了補丁之後,我們可以再看看目前文件a的情況:

sweetdum@sweetdum-ASUS:sweetdum-ASUS: /GitEx$ cat a
This is the file a.
Fix!!!

果然,多了一個Fix!!!

不過要注意的是,如果master與Fix分支中間有多次提交,它會針對每次提交產生一個patch。

3.兩種patch的比較:

相容性:很明顯,git diff產生的Patch相容性強。如果你在修改的程式碼的官方版本庫不是Git管理的版本庫,那麼你必須使用git diff產生的patch才能讓你的程式碼被專案的維護人接受。

調試功能:對於git diff產生的patch,你可以用git apply --check 查看補丁是否能夠乾淨順利地應用到當前分支中;如果git format-patch 產生的補丁不能打到目前分支,git am會給予提示,並協助你完成打補丁工作,你也可以使用git am -3進行三方合併,詳細的做法可以參考git手冊或《Progit》。從這一點來看,兩者調試功能都很強。

版本庫資訊:由於git format-patch產生的補丁中含有這個補丁開發者的名字,因此在應用補丁時,這個名字會被記錄進版本庫,顯然,這樣做是恰當的。因此,目前使用Git的開源社群往往建議大家使用format-patch產生補丁。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn