The production and application of patch under Linux (transfer)

The production and application of patch under Linux is
transferred from: http://blog.chinaunix.net/u3/100239/showart_1984963.html


1. Command Introduction
First, let's introduce diff and patch. Not all the options in the man online documentation will be described here, nor is it necessary.
99% of the time, we only use a few options. So you must learn these options.
1. diff
--------------------
    NAME
           diff - find differences between two files
    SYNOPSIS
           diff [options] from-file to-file
-------- ----------
simply put, the function of diff is to compare the difference between two files, and then record them, which is the so-called diff patch.


Grammar format:
diff [Options] Source file (folder) Destination file (folder),
is to patch the source file (folder) to make it become the destination file (folder), the term is "upgrade".


The three most commonly used options are described below:
    -r is a recursive option. If this option is set, diff will compare all corresponding files in the source code directories of two different versions, including subdirectory files. 
    The -N option ensures that the patch file will correctly handle cases where files have already been created or deleted.
    The -u option creates patch files in a unified format, which is more compact than the default format.


2. patch
    -----------------
    NAME
       patch - apply a diff file to an original
    SYNOPSIS
           patch [options] [originalfile [patchfile]]
           but usually just
           patch -pnum
    -- --------------
    simply put, patch is to use the patch made by diff to realize the conversion of source file (folder) and destination file (folder).
This means that you can have source files (folders) --> destination files (folders), or destination files (folders) --> source files (folders).


Here are some of the most commonly used options:
    -p0 option to search the destination file (folder) from the current directory
    -p1 option to ignore the first level directory and start the search from the current directory.
**************************************************** **********
Here's an example:
--- old/modules/pcitable Mon Sep 27 11:03:56 1999
+++ new/modules/pcitable Tue Dec 19 20:05:41 2000


    If you use the parameter -p0, it means to find a folder called old from the current directory,
    Look for the pcitable file under modules under it to perform the patch operation.
    If the parameter -p1 is used, it means that the first-level directory (ie, regardless of old) is ignored, and
    the modules folder is searched from the current directory, and pcitable is found under it.
    The premise of this is that the current directory must be the directory where modules are located. The diff patch file can be in any location,
    as long as the path of the diff patch file is specified. Of course, you can use relative paths or absolute paths.
    But I'm generally used to using relative paths.
**************************************************** ********** 


-E option says if an empty file is found, delete it
-R option says "new" and "old" files in the patch file are now swapped (actually It is to patch the new version to make it become the old version.)
The following analysis and solution are combined with specific examples, which are divided into two types: patching a single file and patching multiple files in a folder.
Environment: Log in as armlinux user under RedHat 9.0.
The directory tree is as follows:
    |-- bootloader
    |-- debug
    |-- images
    |-- kernel
    |-- program
    |-- rootfiles
    |-- software
    |-- source
    |-- sysapps
    |-- tmp
    |-- tools


下面在program文件夹下面建立patch文件夹作为实验用,然后进入patch文件夹。


二、为单个文件进行补丁操作
1、建立测试文件test0、test1
[armlinux@lqm patch]$ cat >>test0<<eof< span="">
> 111111
> 111111
> 111111
> EOF
[armlinux@lqm patch]$ more test0
111111
111111
111111
[armlinux@lqm patch]$ cat >>test1<<eof< span="">
> 222222
> 111111
> 222222
> 111111
> EOF
[armlinux@lqm patch]$ more test1
222222
111111
222222
111111


2、使用diff创建补丁test1.patch
[armlinux@lqm patch]$ diff -uN test0 test1 > test1.patch
【注:因为单个文件,所以不需要-r选项。选项顺序没有关系,即可以是-uN,也可以是-Nu。】
[armlinux@lqm patch]$ ls
test0 test1 test1.patch
[armlinux@lqm patch]$ more test1.patch
************************************************************
patch文件的结构
A. 补丁头
补丁头是分别由---/+++开头的两行,用来表示要打补丁的文件。
---开头表示旧文件,
+++开头表示新文件。


一个补丁文件中的多个补丁
一个补丁文件中可能包含以---/+++开头的很多节,每一节用来打一个补丁。
所以在一个补丁文件中可以包含好多个补丁。


B. 块
块是补丁中要修改的地方。
它通常由一部分不用修改的东西开始和结束。他们只是用来表示要修改的位置。
他们通常以@@开始,结束于另一个块的开始或者一个新的补丁头。


块的缩进
块会缩进一列,而这一列是用来表示这一行是要增加还是要删除的。
块的第一列
+号表示这一行是要加上的。
-号表示这一行是要删除的。
没有加号也没有减号表示这里只是引用的而不需要修改。
************************************************************
***diff命令会在补丁文件中记录这两个文件的首次创建时间,如下***
--- test0       2006-08-18 09:12:01.000000000 +0800
+++ test1       2006-08-18 09:13:09.000000000 +0800
@@ -1,3 +1,4 @@
+222222
111111
-111111
+222222
111111
[armlinux@lqm patch]$ patch -p0 < test1.patch
patching file test0
[armlinux@lqm patch]$ ls
test0 test1 test1.patch
[armlinux@lqm patch]$ cat test0
222222
111111
222222
111111


3、去除补丁,恢复旧版本
[armlinux@lqm patch]$ patch -RE -p0 < test1.patch
patching file test0
[armlinux@lqm patch]$ ls
test0 test1 test1.patch
[armlinux@lqm patch]$ cat test0
111111
111111
111111


三、为多个文件进行补丁操作
1、创建测试文件夹
[armlinux@lqm patch]$ mkdir prj0
[armlinux@lqm patch]$ cp test0 prj0
[armlinux@lqm patch]$ ls
prj0 test0 test1 test1.patch
[armlinux@lqm patch]$ cd prj0/
[armlinux@lqm prj0]$ ls
test0
[armlinux@lqm prj0]$ cat >>prj0name<<eof< span="">
> --------
> prj0/prj0name
> --------
> EOF
[armlinux@lqm prj0]$ ls
prj0name test0
[armlinux@lqm prj0]$ cat prj0name
--------
prj0/prj0name
--------
[armlinux@lqm prj0]$ cd ..
[armlinux@lqm patch]$ mkdir prj1
[armlinux@lqm patch]$ cp test1 prj1
[armlinux@lqm patch]$ cd prj1
[armlinux@lqm prj1]$ cat >>prj1name<<eof< span="">
> ---------
> prj1/prj1name
> ---------
> EOF
[armlinux@lqm prj1]$ cat prj1name
---------
prj1/prj1name
---------
[armlinux@lqm prj1]$ cd ..


2、创建补丁
[armlinux@lqm patch]$ diff -uNr prj0 prj1 > prj1.patch
[armlinux@lqm patch]$ more prj1.patch
diff -uNr prj0/prj0name prj1/prj0name
--- prj0/prj0name       2006-08-18 09:25:11.000000000 +0800
+++ prj1/prj0name       1970-01-01 08:00:00.000000000 +0800
@@ -1,3 +0,0 @@
---------
-prj0/prj0name
---------
diff -uNr prj0/prj1name prj1/prj1name
--- prj0/prj1name       1970-01-01 08:00:00.000000000 +0800
+++ prj1/prj1name       2006-08-18 09:26:36.000000000 +0800
@@ -0,0 +1,3 @@
+---------
+prj1/prj1name
+---------
diff -uNr prj0/test0 prj1/test0
--- prj0/test0 2006-08-18 09:23:53.000000000 +0800
+++ prj1/test0 1970-01-01 08:00:00.000000000 +0800
@@ -1,3 +0,0 @@
-111111
-111111
-111111
diff -uNr prj0/test1 prj1/test1
--- prj0/test1 1970-01-01 08:00:00.000000000 +0800
+++ prj1/test1 2006-08-18 09:26:00.000000000 +0800
@@ -0,0 +1,4 @@
+222222
+111111
+222222
+111111
[armlinux@lqm patch]$ ls
prj0 prj1 prj1.patch test0 test1 test1.patch
[armlinux@lqm patch]$ cp prj1.patch ./prj0
[armlinux@lqm patch]$ cd prj0
[armlinux@lqm prj0]$ patch -p1 < prj1.patch 
patching file prj0name
patching file prj1name
patching file test0
patching file test1
[armlinux@lqm prj0]$ ls
prj1name prj1.patch test1
[armlinux@lqm prj0]$ patch -R -p1 < prj1.patch 
patching file prj0name
patching file prj1name
patching file test0
patching file test1
[armlinux@lqm prj0]$ ls
prj0name prj1.patch test0
-------------------------------------------------


四、总结:
1. 单个文件
$ diff –uN from-file to-file >to-file.patch
$ patch –p0 < to-file.patch
$ patch –RE –p0 < to-file.patch


2. 多个文件
$ diff –uNr from-docu to-docu >to-docu.patch
$ patch –p1 < to-docu.patch
$ patch –R –p1

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324813399&siteId=291194637