版本庫間的交互是經過git push和/或git pull命令實現的,這是Git最主要的交互模式,但並非所有。使用補丁文件是另一種交互方式,適用於參與者衆多的大型項目進行分佈式開發。git
Git提供了將提交批量轉換爲補丁文件的命令:git format-patch。該命令後面的參數是一個版本範圍列表,會將包含在此列表中的提交一一轉換爲補丁文件,每一個補丁文件包含一個序號並從提交說明中提取字符串做爲文件名。app
下面演示一下在user1工做區中,如何將master分支的最近3個提交轉換爲補丁文件。分佈式
$ cd /path/to/user1/workspace/hello-world/ $ git checkout master $ git pull
$ git format-patch -s HEAD~3..HEAD 0001-Fix-typo-help-to-help.patch 0002-Add-I18N-support.patch 0003-Translate-for-Chinese.patch
在上面的git format-patch命令中使用了-s參數,會在導出的補丁文件中添加當前用戶的簽名。這個簽名並不是GnuPG式的數字簽名,不過是將做者姓名添加到提交說明中而已,和在本書第2篇開頭介紹的git commit -s命令的效果相同。雖然簽名很不起眼,可是對於以補丁方式提交數據卻很是重要,由於以補丁方式提交可能由於合併衝突或其餘緣由使得最終提交的做者顯示爲管理員(提交者)的ID,在提交說明中加入原始做者的署名信息大概是做者惟一露臉的機會。若是在提交時忘了使用-s參數添加簽名,能夠在用git format-path命令建立補丁文件的時候補救。工具
看一下補丁文件的文件頭,在下面代碼中的第7行能夠看到新增的簽名。ui
1 From d81896e60673771ef1873b27a33f52df75f70515 Mon Sep 17 00:00:00 2001 2 From: user1 <user1@sun.ossxp.com> 3 Date: Mon, 3 Jan 2011 23:48:56 +0800 4 Subject: [PATCH 1/3] Fix typo: -help to --help. 5 6 7 Signed-off-by: user1 <user1@sun.ossxp.com> 8 --- 9 src/main.c | 2 +- 10 1 files changed, 1 insertions(+), 1 deletions(-)
補丁文件有一個相似郵件同樣的文件頭(第1-4行),提交日誌的第一行做爲郵件標題(Subject),其他提交說明做爲郵件內容(若是有的話),文件補丁用三個橫線和提交說明分開。this
實際上這些補丁文件能夠直接拿來做爲郵件發送給項目的負責人。Git提供了一個輔助郵件發送的命令git send-email。下面用該命令將這三個補丁文件以郵件形式發送出去。spa
git send-email *.patch 0001-Fix-typo-help-to-help.patch 0002-Add-I18N-support.patch 0003-Translate-for-Chinese.patch The following files are 8bit, but do not declare a Content-Transfer-Encoding. 0002-Add-I18N-support.patch 0003-Translate-for-Chinese.patch Which 8bit encoding should I declare [UTF-8]? Who should the emails appear to be from? [user1 <user1@sun.ossxp.com>] Emails will be sent from: user1 <user1@sun.ossxp.com> Who should the emails be sent to? jiangxin Message-ID to be used as In-Reply-To for the first email? ... Send this email? ([y]es|[n]o|[q]uit|[a]ll): a ...
命令git send-email提供交互式字符界面,輸入正確的收件人地址,郵件就批量地發送出去了。翻譯
在前面經過git send-email命令發送郵件給jiangxin用戶。如今使用 Linux 上的mail命令檢查一下郵件。設計
$ mail Mail version 8.1.2 01/15/2001. Type ? for help. "/var/mail/jiangxin": 3 messages 3 unread >N 1 user1@sun.ossxp.c Thu Jan 13 18:02 38/1120 [PATCH 1/3] Fix typo: -help to --help. N 2 user1@sun.ossxp.c Thu Jan 13 18:02 227/6207 =?UTF-8?q?=5BPATCH=202/3=5D=20Add=20I18N=20support=2E?= N 3 user1@sun.ossxp.c Thu Jan 13 18:02 95/2893 =?UTF-8?q?=5BPATCH=203/3=5D=20Translate=20for=20Chinese=2E?= &
若是郵件不止這三封,須要將三個包含補丁的郵件挑選出來保存到另外的文件中。 在 mail 命令的提示符(&)下輸入命令。3d
& s 1-3 user1-mail-archive "user1-mail-archive" [New file] & q
上面的操做在本地建立了一個由開發者user1的補丁郵件組成的歸檔文件user1-mail-archive,這個文件是mbox格式的,能夠用mail命令打開。
$ mail -f user1-mail-archive Mail version 8.1.2 01/15/2001. Type ? for help. "user1-mail-archive": 3 messages > 1 user1@sun.ossxp.c Thu Jan 13 18:02 38/1121 [PATCH 1/3] Fix typo: -help to --help. 2 user1@sun.ossxp.c Thu Jan 13 18:02 227/6208 =?UTF-8?q?=5BPATCH=202/3=5D=20Add=20I18N=20support=2E?= 3 user1@sun.ossxp.c Thu Jan 13 18:02 95/2894 =?UTF-8?q?=5BPATCH=203/3=5D=20Translate=20for=20Chinese=2E?= & q
保存在mbox中的郵件能夠批量的應用在版本庫中,使用git am命令。am是apply email的縮寫。下面就演示一下如何應用補丁。
$ git checkout -b user1 HEAD~3 Switched to a new branch 'user1'
$ git am user1-mail-archive Applying: Fix typo: -help to --help. Applying: Add I18N support. Applying: Translate for Chinese.
$ git log -3 --pretty=fuller commit 2d9276af9df1a2fdb71d1e7c9ac6dff88b2920a1 Author: Jiang Xin <jiangxin@ossxp.com> AuthorDate: Thu Jan 13 18:02:03 2011 +0800 Commit: user1 <user1@sun.ossxp.com> CommitDate: Thu Jan 13 18:21:16 2011 +0800 Translate for Chinese. Signed-off-by: Jiang Xin <jiangxin@ossxp.com> Signed-off-by: user1 <user1@sun.ossxp.com> commit 41227f492ad37cdd99444a5f5cc0c27288f2bca4 Author: Jiang Xin <jiangxin@ossxp.com> AuthorDate: Thu Jan 13 18:02:02 2011 +0800 Commit: user1 <user1@sun.ossxp.com> CommitDate: Thu Jan 13 18:21:15 2011 +0800 Add I18N support. Signed-off-by: Jiang Xin <jiangxin@ossxp.com> Signed-off-by: user1 <user1@sun.ossxp.com> commit 4a3380fb7ae90039633dec84acc2aab85398efad Author: user1 <user1@sun.ossxp.com> AuthorDate: Thu Jan 13 18:02:01 2011 +0800 Commit: user1 <user1@sun.ossxp.com> CommitDate: Thu Jan 13 18:21:15 2011 +0800 Fix typo: -help to --help. Signed-off-by: user1 <user1@sun.ossxp.com>
從提交信息上能夠看出:
提交的時間信息使用了郵件發送的時間。
做者(Author)的信息被保留,和補丁文件中的一致。
提交者(Commit)全都設置爲user1,由於提交是在user1的工做區完成的。
提交說明中的簽名信息被保留。實際上git am命令也能夠提供-s參數,在提交說明中附加執行命令用戶的簽名。
對於不習慣在控制檯用mail命令接收郵件的用戶,能夠經過郵件附件,U盤或其餘方式獲取git format-patch生成的補丁文件,將補丁文件保存在本地,經過管道符調用git am命令應用補丁。
$ ls *.patch 0001-Fix-typo-help-to-help.patch 0002-Add-I18N-support.patch 0003-Translate-for-Chinese.patch $ cat *.patch | git am Applying: Fix typo: -help to --help. Applying: Add I18N support. Applying: Translate for Chinese.
Git還提供一個命令git apply,能夠應用通常格式的補丁文件,可是不能執行提交,也不能保持補丁中的做者信息。
一個複雜功能的開發必定是由多個提交來完成的,對於在以接收和應用補丁文件爲開發模式的項目中,複雜的功能須要經過多個補丁文件來完成。補丁文件由於要通過審覈才能被接受,所以針對一個功能的多個補丁文件必定要保證各個都是精品:補丁1用來完成一個功能點,補丁2用來完成第二個功能點,等等。必定不能出現這樣的狀況:補丁3用於修正補丁1的錯誤,補丁10改正了補丁7中的文字錯誤,等等。這樣就帶來補丁管理的難題。
實際上基於特性分支的開發又未嘗不是如此?在將特性分支歸併到開發主線前,要接受團隊的評審,特性分支的開發者必定想將特性分支上的提交進行重整,把一些提交合並或者拆分。使用變基命令能夠實現提交的重整,可是操做起來會比較困難,有什麼好辦法呢?
Stacked Git(http://www.procode.org/stgit/)簡稱StGit就是解決上述兩個難題的答案。實際上StGit在設計上參考了一個著名的補丁管理工具Quilt,而且能夠輸出Quilt兼容的補丁列表。
StGit是一個Python項目,安裝起來仍是很方便的。在Debian/Ubuntu下,能夠直接經過包管理器安裝:
$ sudo aptitude install stgit stgit-contrib
下面仍是用hello-world版本庫,進行StGit的實踐。
$ cd /path/to/my/workspace/ $ git clone file:///path/to/repos/hello-world.git stgit-demo $ cd stgit-demo
$ stg init
$ stg series
$ stg uncommit -n 3 Uncommitting 3 patches ... Now at patch "translate-for-chinese" done
第一列是補丁的狀態符號。加號(+)表明該補丁已經應用在版本庫中,大於號(>)用於標識當前的補丁。
$ stg ser + fix-typo-help-to-help + add-i18n-support > translate-for-chinese
$ git log -3 --oneline c4acab2 Translate for Chinese. 683448a Add I18N support. d81896e Fix typo: -help to --help.
$ stg pop Popped translate-for-chinese Now at patch "add-i18n-support" $ stg pop -a Popped add-i18n-support -- fix-typo-help-to-help No patch applied
$ git log -3 --oneline 10765a7 Bugfix: allow spaces in username. 0881ca3 Refactor: use getopt_long for arguments parsing. ebcf6d6 blank commit for GnuPG-signed tag test.
$ stg ser - fix-typo-help-to-help - add-i18n-support - translate-for-chinese
$ stg push Pushing patch "fix-typo-help-to-help" ... done (unmodified) Now at patch "fix-typo-help-to-help" $ stg goto add-i18n-support Pushing patch "add-i18n-support" ... done (unmodified) Now at patch "add-i18n-support"
$ cd src/ $ rm locale/helloworld.pot $ make po xgettext -s -k_ -o locale/helloworld.pot main.c msgmerge locale/zh_CN/LC_MESSAGES/helloworld.po locale/helloworld.pot -o locale/temp.po . 完成。 mv locale/temp.po locale/zh_CN/LC_MESSAGES/helloworld.po
$ git status -s M locale/helloworld.pot M locale/zh_CN/LC_MESSAGES/helloworld.po
$ stg refresh Now at patch "add-i18n-support"
$ git status -s
$ stg show ...
$ stg push Pushing patch "translate-for-chinese" ... done (conflict) Error: 1 merge conflict(s) CONFLICT (content): Merge conflict in src/locale/zh_CN/LC_MESSAGES/helloworld.po Now at patch "translate-for-chinese"
50 " hello -h, --help\n" 51 " 顯示本幫助頁。\n" ... 61 msgid "Hi," 62 msgstr "您好,"
$ git add locale/zh_CN/LC_MESSAGES/helloworld.po
$ stg refresh Now at patch "translate-for-chinese" $ git status -s
$ ./hello 世界你好。 (version: v1.0-5-g733c6ea) $ ./hello Jiang Xin 您好, Jiang Xin. (version: v1.0-5-g733c6ea) $ ./hello -h ...
$ cd /path/to/my/workspace/stgit-demo/ $ stg export -d patches Checking for changes in the working directory ... done
$ ls patches/ add-i18n-support fix-typo-help-to-help series translate-for-chinese
$ cat patches/series # This series applies on GIT commit d81896e60673771ef1873b27a33f52df75f70515 fix-typo-help-to-help add-i18n-support translate-for-chinese
經過上面的演示能夠看出StGit能夠很是方便的對提交進行整理,整理提交時無需使用複雜的變基命令,而是採用:提交StGit化,修改文件,執行stg refresh的工做流程便可更新補丁和提交。StGit還能夠將補丁導出爲補丁文件,雖然導出的補丁文件沒有像git format-patch那樣加上表明順序的數字前綴,可是用文件series標註了補丁文件的前後順序。實際上能夠在執行stg export時添加-n參數爲補丁文件添加數字前綴。
StGit還有一些功能,如合併補丁/提交,插入新補丁/提交等,
Quilt是一款補丁列表管理軟件,用Shell語言開發,安裝也很簡單,在Debian/Ubuntu上直接用下面的命令便可安裝:
$ sudo aptitude install quilt
Quilt約定俗成將補丁集放在項目根目錄下的子目錄patches中,不然須要經過環境變量QUILT_PATCHES對路徑進行設置。爲了減小麻煩,在上面用stg export導出補丁的時候就導出到了patches目錄下。
簡單說一下Quilt的使用,會發現真的和StGit很像,其實是先有的Quilt,後有的StGit。
$ git reset --hard HEAD~3 $ rm -rf src/locale/
$ quilt series 01-fix-typo-help-to-help 02-add-i18n-support 03-translate-for-chinese
$ quilt push Applying patch 01-fix-typo-help-to-help patching file src/main.c Now at patch 01-fix-typo-help-to-help
$ quilt next 02-add-i18n-support
$ quilt push -a Applying patch 02-add-i18n-support patching file src/Makefile patching file src/locale/helloworld.pot patching file src/locale/zh_CN/LC_MESSAGES/helloworld.po patching file src/main.c Applying patch 03-translate-for-chinese patching file src/locale/zh_CN/LC_MESSAGES/helloworld.po Now at patch 03-translate-for-chinese