補丁,當本地版本庫與遠程版本庫未直接進行關聯,需要通過補丁來進行相關對象的同步(通常是commit)。
補丁的內容
git format-patch generates one email message for each selected commit
git format-patch generates an email message complete with headers that list the commit author, the commit date, and the commit log message associated with the change
format-patch命令爲每次提交都生成一個補丁,補丁的內容頭部是郵件的一些信息,和提交相關的信息,包含提交作者,日期,提交的日誌信息。內容體,是當前提交與其父提交的比較結果(git diff)。
補丁的創建,發送,應用。實際工作的應用場景很少。
官網地址:https://git-scm.com/docs,patching部分和Email部分
1、創建
使用git format-patch生成補丁。它的選項或者是參數有四種形式,
- 第一種形式-n,指最近的n次提交,每次提交都生成一份補丁。
- 第二種形式range,在範圍之內的提交生成補丁。
- 第三種形式是commit的標識,例如引用標識,ID等類似的提交名稱
- 第四種形式是branch的名稱。
在第二種形式中,若range中存在合併的操作,它生成補丁的步驟如下,
- 它會從end開始沿着提交歷史找尋所有的父提交,祖父提交直到初始提交。
- 之後排除由start開始沿着提交歷史找尋到的所有父提交,祖父提交,並且包含start本身。
- 最後排除所有合併的提交,也可以理解爲有多個父提交的提交。
假定目前有兩個分支alt,master分支,範圍爲C..F。
第一步,從F開始尋找所有父提交,祖父提交,它們包括A,B,C,D,E,F,X,Y,Z。即全部包括
第二步,排除由C開始尋找到的所有父提交,祖父提交,包含C自身。此時剩餘D,E,F,X,Y,Z
第三步,排除所有合併的提交,即E,此時剩餘D,F,X,Y,Z。
執行git format-patch C..F會爲D,F,X,Y,Z每個提交各生成一份補丁。
第三種形式本質是commitID..HEAD之間的補丁。它與commitID,HEAD有關。執行git format-path master~1與 -1是等價的。
第四種形式分兩種情況,若選項中的分支名稱與當前分支名稱相同,無任何結果。若分支名稱與當前分支名稱不同,例如在master分支上執行git format-patch alt,會生成alt分支上沒有的,而master分支上存在的提交。
本質是當前分支與選項分支的差集,並且排除合併的提交。
格式爲:
git format-patch [-k] [(-o|--output-directory) <dir> | --stdout] [--no-thread | --thread[=<style>]] [(--attach|--inline)[=<boundary>] | --no-attach] [-s | --signoff] [--signature=<signature> | --no-signature] [--signature-file=<file>] [-n | --numbered | -N | --no-numbered] [--start-number <n>] [--numbered-files] [--in-reply-to=<message id>] [--suffix=.<sfx>] [--ignore-if-in-upstream] [--cover-from-description=<mode>] [--rfc] [--subject-prefix=<subject prefix>] [(--reroll-count|-v) <n>] [--to=<email>] [--cc=<email>] [--[no-]cover-letter] [--quiet] [--no-notes | --notes[=<ref>]] [--interdiff=<previous>] [--range-diff=<previous> [--creation-factor=<percent>]] [--progress] [<common diff options>] [ <since> | <revision range>]
它的大部分選項分爲三個部分,
第一部分,補丁文件,例如補丁文件的名稱,存放的路徑等等。
第二部分,補丁文件的內容,例如補丁文件的格式。
第三部分,生成補丁的條件,默認情況下選取提交歷史範圍,爲該範圍的每個提交都生成一份補丁文件。
只需要記住條件和文件的選項。
文件:
--no-numbered:文件名中不包含數字。
--start-number:開始數字,默認值爲1,所以生成的補丁文件有0001。
--numbered-files:文件名稱只顯示數字。
--suffix:文件的後綴,默認值爲patch,可以設置爲txt。
條件:
-n,--numbered:最多n個提交。
--ignore-if-in-upstream:忽略當前提交區間。
--root:爲根提交生成補丁,由於根提交沒有父提交,所以通過顯示的內容也不是diff結果。
其他選項略。
2、發送
使用git send-email發送補丁。本質通過git send-email發送郵件,郵件的內容是補丁文件。
通過命令行方式發送郵件非常繁瑣,它需要大約兩部分配置,
第一部分是服務器相關的,郵件服務器地址,用戶名,端口,協議等等。
第二部分是郵件內容相關的,郵件主題,郵件發送者,接收人,抄送者等等。
格式爲:
git send-email [<options>] <file|directory|rev-list options>…
郵件相關:
--from=<address>:發送人
--to=<address>:收件人
--bcc=<address>:抄送人
--cc=<address>:抄送人
--reply-to=<address>:回覆人
--subject=<string>:郵件的標題
其他不常見的選項略。
內容相關:
--8bit-encoding=<encoding>:略。
--compose-encoding=<encoding>:略。
--transfer-encoding=<encoding>:略。
其他不常見的選項略。
3、應用
Git應用補丁的指令有兩個,apply,am。
引用apply命令手冊的定義:
Reads the supplied diff output (i.e. "a patch") and applies it to files. When running from a subdirectory in a repository, patched paths outside the directory are ignored. With the --index option the patch is also applied to the index, and with the --cached option the patch is only applied to the index. Without these options, the command applies the patch only to files, and does not require them to be in a Git repository.
根據當前提交與父提交的比較結果生成補丁文件。在版本庫應用補丁時,默認情況下只應用到工作目錄,沒有對應目錄結構的被忽略,添加--index應用到索引,添加--cached只應用到索引。
This command applies the patch but does not create a commit.
命令不會產生提交。am命令會產生。
3.1 apply
格式爲:
git apply [--stat] [--numstat] [--summary] [--check] [--index | --intent-to-add] [--3way] [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse] [--allow-binary-replacement | --binary] [--reject] [-z] [-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached] [--ignore-space-change | --ignore-whitespace] [--whitespace=(nowarn|warn|fix|error|error-all)] [--exclude=<path>] [--include=<path>] [--directory=<root>] [--verbose] [--unsafe-paths] [<patch>…]
它只關注應用單個補丁這個過程。
它的選項分爲三類,模擬運行,實際運行,和雜項。
最常見的是模擬運行和實際運行的選項。
模擬運行最常見的選項是check,實際運行最常見的選項directory,-3way。
模擬運行:
--stat:模擬運行,只顯示統計信息
--numstat:模擬運行,只顯示數字統計信息。
--summary:模擬運行,只顯示統計信息中的總結部分
--check:模擬運行,檢查是否存在衝突。
--index:與模擬運行的選項配合使用,表示會更新index。
--cached:TODO。
--intent-to-add:與模擬運行的選項配合使用,表示忽略新增文件類型的修改。
--apply:與模擬運行的選項配合使用,表示會實際運行。
實際運行:
--3way:與am的選項含義相同,衝突發生時,採用合併。
--reverse:逆序應用補丁。
--reject: 默認情況下是all or nothing,添加該選項後,只會拒絕失敗的補丁,它不會對已經成功的補丁產生影響。
-p<n>,選取補丁文件路徑的後幾層級,例如a/b/c/d.patch,-p2之後,補丁的路徑變爲c/d.patch。感覺沒啥用。
--directory=<root>:指定補丁的根目錄。
--include,--exclude,指定包含哪些,排除哪些,值爲補丁文件的路徑集合。
其他:
-v, verbose公共選項,略。
--ignore-whitespace, --ignore-space-change, --whitespace=<action>,在am命令中已介紹過。
--inaccurate-eof:修復文件末尾比較時產生的Bug。
--recount:不相信原始的行號,重新計算行號,通常不會有人手動修改補丁文件吧。
--allow-binary-replacement,--binary:TODO。感覺無意義。
--unsafe-paths:TODO, 感覺無意義。
--unidiff-zero。
3.2 am
格式爲:
git am [--signoff] [--keep] [--[no-]keep-cr] [--[no-]utf8] [--[no-]3way] [--interactive] [--committer-date-is-author-date] [--ignore-date] [--ignore-space-change | --ignore-whitespace] [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>] [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet] [--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>] [(<mbox> | <Maildir>)…]
am的選項大致可以分爲三類。
第一類是公共選項,例如-q quiet,--interactive, -[no-]utf-8。略。
第二類是與提交有關的,因爲am會創建提交對象。
第三類是控制整個應用補丁過程的。
提交信息:
--signoff:添加簽名,或者署名。
-S[keyid], --gpg-sign=<keyid>:gpg簽名
--[no]message-id:是否將郵件中的messageId添加到commit日誌信息中
--ignore-space-change, --ignore-whitespace, --white-space=<option>:是否忽略空格。
--committer-date-is-author-date:提交日期使用原始日期。
--ignore-date:忽略原始日期。
過程:
--3,--3way,應用補丁存在衝突時,使用合併策略。
--skip,跳過當前補丁。
-r, --resolved,衝突已解決。
--resolvedmsg=<msg>,衝突解決的日誌信息。
--abort,中斷, --quit,退出,--continue,繼續。
其他:
--patch-format:指定補丁的格式,沒什麼用
--show-current-patch=[diff | raw],也沒啥用。