鍍金池/ 教程/ Java/ 簽署工作
腳本 GitHub
Git 鉤子
分支與合并
撤消操作
5.4 總結(jié)
Git 對象
變基
Bash 中的 Git
補丁
Git 引用
項目分享與更新
總結(jié)
GitWeb
Visual Studio 中的 Git
外部系統(tǒng)
替換
Zsh 中的 Git
Git 命令
打包
使用強制策略的一個例子
總結(jié)
簽署工作
分支開發(fā)工作流
遠程分支
總結(jié)
安裝 Git
Powershell 中的 Git
快照基礎(chǔ)
管理組織
Git 與其他系統(tǒng)
在服務(wù)器上搭建 Git
GitHub
Git 別名
憑證存儲
維護與數(shù)據(jù)恢復
包文件
子模塊
將 Git 嵌入你的應用
獲取幫助
對項目做出貢獻
Git 分支
使用 Git 調(diào)試
Libgit2
Git 基礎(chǔ)
郵件
Git 內(nèi)部原理
維護項目
調(diào)試
向一個項目貢獻
總結(jié)
維護項目
命令行
分布式 Git
總結(jié)
JGit
儲藏與清理
管理
獲取與創(chuàng)建項目
總結(jié)
Rerere
Git 簡史
Smart HTTP
總結(jié)
Eclipse 中的 Git
總結(jié)
引用規(guī)格
傳輸協(xié)議
查看提交歷史
自定義 Git
底層命令
Git 守護進程
搜索
Git 基礎(chǔ)
Git 工具
關(guān)于版本控制
環(huán)境變量
其它環(huán)境中的 Git
高級合并
服務(wù)器上的 Git
第三方托管的選擇
遷移到 Git
遠程倉庫的使用
GitLab
生成 SSH 公鑰
分支的新建與合并
配置服務(wù)器
交互式暫存
重寫歷史
重置揭密
Git 屬性
總結(jié)
初次運行 Git 前的配置
記錄每次更新到倉庫
總結(jié)
分支管理
打標簽
檢查與比較

簽署工作

Git 雖然是密碼級安全的,但它不是萬無一失的。 如果你從因特網(wǎng)上的其他人那里拿取工作,并且想要驗證提交是不是真正地來自于可信來源,Git 提供了幾種通過 GPG 來簽署和驗證工作的方式。

GPG 介紹

首先,在開始簽名之前你需要先配置 GPG 并安裝個人密鑰。

$ gpg --list-keys
/Users/schacon/.gnupg/pubring.gpg
---------------------------------
pub   2048R/0A46826A 2014-06-04
uid                  Scott Chacon (Git signing key) <schacon@gmail.com>
sub   2048R/874529A9 2014-06-04

如果你還沒有安裝一個密鑰,可以使用 gpg --gen-key 生成一個。

gpg --gen-key

一旦你有一個可以簽署的私鑰,可以通過設(shè)置 Git 的 user.signingkey 選項來簽署。

git config --global user.signingkey 0A46826A

現(xiàn)在 Git 默認使用你的密鑰來簽署標簽與提交。

簽署標簽

如果已經(jīng)設(shè)置好一個 GPG 私鑰,可以使用它來簽署新的標簽。 所有需要做的只是使用 -s 代替 -a 即可:

$ git tag -s v1.5 -m 'my signed 1.5 tag'

You need a passphrase to unlock the secret key for
user: "Ben Straub <ben@straub.cc>"
2048-bit RSA key, ID 800430EB, created 2014-05-04

如果在那個標簽上運行 git show,會看到你的 GPG 簽名附屬在后面:

$ git show v1.5
tag v1.5
Tagger: Ben Straub <ben@straub.cc>
Date:   Sat May 3 20:29:41 2014 -0700

my signed 1.5 tag
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAABAgAGBQJTZbQlAAoJEF0+sviABDDrZbQH/09PfE51KPVPlanr6q1v4/Ut
LQxfojUWiLQdg2ESJItkcuweYg+kc3HCyFejeDIBw9dpXt00rY26p05qrpnG+85b
hM1/PswpPLuBSr+oCIDj5GMC2r2iEKsfv2fJbNW8iWAXVLoWZRF8B0MfqX/YTMbm
ecorc4iXzQu7tupRihslbNkfvfciMnSDeSvzCpWAHl7h8Wj6hhqePmLm9lAYqnKp
8S5B/1SSQuEAjRZgI4IexpZoeKGVDptPHxLLS38fozsyi0QyDyzEgJxcJQVMXxVi
RUysgqjcpT8+iQM1PblGfHR4XAhuOqN5Fx06PSaFZhqvWFezJ28/CLyX5q+oIVk=
=EFTF
-----END PGP SIGNATURE-----

commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

驗證標簽

要驗證一個簽署的標簽,可以運行 git tag -v [tag-name]。 這個命令使用 GPG 來驗證簽名。 為了驗證能正常工作,簽署者的公鑰需要在你的鑰匙鏈中。

$ git tag -v v1.4.2.1
object 883653babd8ee7ea23e6a5c392bb739348b1eb61
type commit
tag v1.4.2.1
tagger Junio C Hamano <junkio@cox.net> 1158138501 -0700

GIT 1.4.2.1

Minor fixes since 1.4.2, including git-mv and git-http with alternates.
gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
gpg: Good signature from "Junio C Hamano <junkio@cox.net>"
gpg:                 aka "[jpeg image of size 1513]"
Primary key fingerprint: 3565 2A26 2040 E066 C9A7  4A7D C0C6 D9A4 F311 9B9A

如果沒有簽署者的公鑰,那么你將會得到類似下面的東西:

gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
gpg: Can't check signature: public key not found
error: could not verify the tag 'v1.4.2.1'

簽署提交

在最新版本的 Git 中(v1.7.9 及以上),也可以簽署個人提交。 如果相對于標簽而言你對直接簽署到提交更感興趣的話,所有要做的只是增加一個 -S 到 git commit 命令。

$ git commit -a -S -m 'signed commit'

You need a passphrase to unlock the secret key for
user: "Scott Chacon (Git signing key) <schacon@gmail.com>"
2048-bit RSA key, ID 0A46826A, created 2014-06-04

[master 5c3386c] signed commit
 4 files changed, 4 insertions(+), 24 deletions(-)
 rewrite Rakefile (100%)
 create mode 100644 lib/git.rb

git log 也有一個 --show-signature 選項來查看及驗證這些簽名。

$ git log --show-signature -1
commit 5c3386cf54bba0a33a32da706aa52bc0155503c2
gpg: Signature made Wed Jun  4 19:49:17 2014 PDT using RSA key ID 0A46826A
gpg: Good signature from "Scott Chacon (Git signing key) <schacon@gmail.com>"
Author: Scott Chacon <schacon@gmail.com>
Date:   Wed Jun 4 19:49:17 2014 -0700

    signed commit

另外,也可以配置 git log 來驗證任何找到的簽名并將它們以 %G? 格式列在輸出中。

$ git log --pretty="format:%h %G? %aN  %s"

5c3386c G Scott Chacon  signed commit
ca82a6d N Scott Chacon  changed the version number
085bb3b N Scott Chacon  removed unnecessary test code
a11bef0 N Scott Chacon  first commit

這里我們可以看到只有最后一次提交是簽署并有效的,而之前的提交都不是。

在 Git 1.8.3 及以后的版本中,“git merge” 與“git pull” 可以使用 --verify-signatures 選項來檢查并拒絕沒有攜帶可信 GPG 簽名的提交。

如果使用這個選項來合并一個包含未簽名或有效的提交的分支時,合并不會生效。

$ git merge --verify-signatures non-verify
fatal: Commit ab06180 does not have a GPG signature.

如果合并包含的只有有效的簽名的提交,合并命令會提示所有的簽名它已經(jīng)檢查過了然后會繼續(xù)向前。

$ git merge --verify-signatures signed-branch
Commit 13ad65e has a good GPG signature by Scott Chacon (Git signing key) <schacon@gmail.com>
Updating 5c3386c..13ad65e
Fast-forward
 README | 2 ++
 1 file changed, 2 insertions(+)

也可以給 git merge 命令附加 -S 選項來簽署自己生成的合并提交。 下面的例子演示了驗證將要合并的分支的每一個提交都是簽名的并且簽署最后生成的合并提交。

$ git merge --verify-signatures -S  signed-branch
Commit 13ad65e has a good GPG signature by Scott Chacon (Git signing key) <schacon@gmail.com>

You need a passphrase to unlock the secret key for
user: "Scott Chacon (Git signing key) <schacon@gmail.com>"
2048-bit RSA key, ID 0A46826A, created 2014-06-04

Merge made by the 'recursive' strategy.
 README | 2 ++
 1 file changed, 2 insertions(+)

每個人必須簽署

簽署標簽與提交很棒,但是如果決定在正常的工作流程中使用它,你必須確保團隊中的每一個人都理解如何這樣做。 如果沒有,你將會花費大量時間幫助其他人找出并用簽名的版本重寫提交。 在采用簽署成為標準工作流程的一部分前,確保你完全理解 GPG 及簽署帶來的好處。