]>
Commit | Line | Data |
---|---|---|
11b17afc JH |
1 | From: Junio C Hamano <gitster@pobox.com> |
2 | Date: Tue, 17 Jan 2011 13:00:00 -0800 | |
3 | Subject: Using signed tag in pull requests | |
4 | Abstract: Beginning v1.7.9, a contributor can push a signed tag to her | |
5 | publishing repository and ask her integrator to pull it. This assures the | |
6 | integrator that the pulled history is authentic and allows others to | |
7 | later validate it. | |
8 | Content-type: text/asciidoc | |
9 | ||
10 | Using signed tag in pull requests | |
11 | ================================= | |
12 | ||
13 | A typical distributed workflow using Git is for a contributor to fork a | |
14 | project, build on it, publish the result to her public repository, and ask | |
15 | the "upstream" person (often the owner of the project where she forked | |
16 | from) to pull from her public repository. Requesting such a "pull" is made | |
17 | easy by the `git request-pull` command. | |
18 | ||
19 | Earlier, a typical pull request may have started like this: | |
20 | ||
21 | ------------ | |
22 | The following changes since commit 406da78032179...: | |
23 | ||
24 | Froboz 3.2 (2011-09-30 14:20:57 -0700) | |
25 | ||
26 | are available in the git repository at: | |
27 | ||
28 | example.com:/git/froboz.git for-xyzzy | |
29 | ------------ | |
30 | ||
31 | followed by a shortlog of the changes and a diffstat. | |
32 | ||
33 | The request was for a branch name (e.g. `for-xyzzy`) in the public | |
34 | repository of the contributor, and even though it stated where the | |
35 | contributor forked her work from, the message did not say anything about | |
36 | the commit to expect at the tip of the for-xyzzy branch. If the site that | |
37 | hosts the public repository of the contributor cannot be fully trusted, it | |
38 | was unnecessarily hard to make sure what was pulled by the integrator was | |
39 | genuinely what the contributor had produced for the project. Also there | |
40 | was no easy way for third-party auditors to later verify the resulting | |
41 | history. | |
42 | ||
43 | Starting from Git release v1.7.9, a contributor can add a signed tag to | |
44 | the commit at the tip of the history and ask the integrator to pull that | |
45 | signed tag. When the integrator runs `git pull`, the signed tag is | |
46 | automatically verified to assure that the history is not tampered with. | |
47 | In addition, the resulting merge commit records the content of the signed | |
48 | tag, so that other people can verify that the branch merged by the | |
49 | integrator was signed by the contributor, without fetching the signed tag | |
50 | used to validate the pull request separately and keeping it in the refs | |
51 | namespace. | |
52 | ||
53 | This document describes the workflow between the contributor and the | |
54 | integrator, using Git v1.7.9 or later. | |
55 | ||
56 | ||
57 | A contributor or a lieutenant | |
58 | ----------------------------- | |
59 | ||
60 | After preparing her work to be pulled, the contributor uses `git tag -s` | |
61 | to create a signed tag: | |
62 | ||
63 | ------------ | |
64 | $ git checkout work | |
65 | $ ... "git pull" from sublieutenants, "git commit" your own work ... | |
66 | $ git tag -s -m "Completed frotz feature" frotz-for-xyzzy work | |
67 | ------------ | |
68 | ||
69 | Note that this example uses the `-m` option to create a signed tag with | |
70 | just a one-liner message, but this is for illustration purposes only. It | |
71 | is advisable to compose a well-written explanation of what the topic does | |
72 | to justify why it is worthwhile for the integrator to pull it, as this | |
73 | message will eventually become part of the final history after the | |
74 | integrator responds to the pull request (as we will see later). | |
75 | ||
76 | Then she pushes the tag out to her public repository: | |
77 | ||
78 | ------------ | |
79 | $ git push example.com:/git/froboz.git/ +frotz-for-xyzzy | |
80 | ------------ | |
81 | ||
82 | There is no need to push the `work` branch or anything else. | |
83 | ||
84 | Note that the above command line used a plus sign at the beginning of | |
85 | `+frotz-for-xyzzy` to allow forcing the update of a tag, as the same | |
86 | contributor may want to reuse a signed tag with the same name after the | |
87 | previous pull request has already been responded to. | |
88 | ||
89 | The contributor then prepares a message to request a "pull": | |
90 | ||
91 | ------------ | |
92 | $ git request-pull v3.2 example.com:/git/froboz.git/ frotz-for-xyzzy >msg.txt | |
93 | ------------ | |
94 | ||
95 | The arguments are: | |
96 | ||
97 | . the version of the integrator's commit the contributor based her work on; | |
98 | . the URL of the repository, to which the contributor has pushed what she | |
99 | wants to get pulled; and | |
100 | . the name of the tag the contributor wants to get pulled (earlier, she could | |
101 | write only a branch name here). | |
102 | ||
103 | The resulting msg.txt file begins like so: | |
104 | ||
105 | ------------ | |
106 | The following changes since commit 406da78032179...: | |
107 | ||
108 | Froboz 3.2 (2011-09-30 14:20:57 -0700) | |
109 | ||
110 | are available in the git repository at: | |
111 | ||
2ad9ba03 | 112 | example.com:/git/froboz.git tags/frotz-for-xyzzy |
11b17afc JH |
113 | |
114 | for you to fetch changes up to 703f05ad5835c...: | |
115 | ||
116 | Add tests and documentation for frotz (2011-12-02 10:02:52 -0800) | |
117 | ||
118 | ----------------------------------------------- | |
119 | Completed frotz feature | |
120 | ----------------------------------------------- | |
121 | ------------ | |
122 | ||
123 | followed by a shortlog of the changes and a diffstat. Comparing this with | |
124 | the earlier illustration of the output from the traditional `git request-pull` | |
125 | command, the reader should notice that: | |
126 | ||
127 | . The tip commit to expect is shown to the integrator; and | |
128 | . The signed tag message is shown prominently between the dashed lines | |
129 | before the shortlog. | |
130 | ||
131 | The latter is why the contributor would want to justify why pulling her | |
132 | work is worthwhile when creating the signed tag. The contributor then | |
133 | opens her favorite MUA, reads msg.txt, edits and sends it to her upstream | |
134 | integrator. | |
135 | ||
136 | ||
137 | Integrator | |
138 | ---------- | |
139 | ||
140 | After receiving such a pull request message, the integrator fetches and | |
141 | integrates the tag named in the request, with: | |
142 | ||
143 | ------------ | |
2ad9ba03 | 144 | $ git pull example.com:/git/froboz.git/ tags/frotz-for-xyzzy |
11b17afc JH |
145 | ------------ |
146 | ||
147 | This operation will always open an editor to allow the integrator to fine | |
148 | tune the commit log message when merging a signed tag. Also, pulling a | |
149 | signed tag will always create a merge commit even when the integrator does | |
150 | not have any new commit since the contributor's work forked (i.e. 'fast | |
151 | forward'), so that the integrator can properly explain what the merge is | |
152 | about and why it was made. | |
153 | ||
154 | In the editor, the integrator will see something like this: | |
155 | ||
156 | ------------ | |
157 | Merge tag 'frotz-for-xyzzy' of example.com:/git/froboz.git/ | |
158 | ||
159 | Completed frotz feature | |
160 | # gpg: Signature made Fri 02 Dec 2011 10:03:01 AM PST using RSA key ID 96AFE6CB | |
161 | # gpg: Good signature from "Con Tributor <nitfol@example.com>" | |
162 | ------------ | |
163 | ||
164 | Notice that the message recorded in the signed tag "Completed frotz | |
165 | feature" appears here, and again that is why it is important for the | |
166 | contributor to explain her work well when creating the signed tag. | |
167 | ||
168 | As usual, the lines commented with `#` are stripped out. The resulting | |
169 | commit records the signed tag used for this validation in a hidden field | |
170 | so that it can later be used by others to audit the history. There is no | |
171 | need for the integrator to keep a separate copy of the tag in his | |
172 | repository (i.e. `git tag -l` won't list the `frotz-for-xyzzy` tag in the | |
173 | above example), and there is no need to publish the tag to his public | |
174 | repository, either. | |
175 | ||
176 | After the integrator responds to the pull request and her work becomes | |
177 | part of the permanent history, the contributor can remove the tag from | |
178 | her public repository, if she chooses, in order to keep the tag namespace | |
179 | of her public repository clean, with: | |
180 | ||
181 | ------------ | |
182 | $ git push example.com:/git/froboz.git :frotz-for-xyzzy | |
183 | ------------ | |
184 | ||
185 | ||
186 | Auditors | |
187 | -------- | |
188 | ||
189 | The `--show-signature` option can be given to `git log` or `git show` and | |
190 | shows the verification status of the embedded signed tag in merge commits | |
191 | created when the integrator responded to a pull request of a signed tag. | |
192 | ||
193 | A typical output from `git show --show-signature` may look like this: | |
194 | ||
195 | ------------ | |
196 | $ git show --show-signature | |
197 | commit 02306ef6a3498a39118aef9df7975bdb50091585 | |
198 | merged tag 'frotz-for-xyzzy' | |
199 | gpg: Signature made Fri 06 Jan 2012 12:41:49 PM PST using RSA key ID 96AFE6CB | |
200 | gpg: Good signature from "Con Tributor <nitfol@example.com>" | |
201 | Merge: 406da78 703f05a | |
202 | Author: Inte Grator <xyzzy@example.com> | |
203 | Date: Tue Jan 17 13:49:41 2012 -0800 | |
204 | ||
205 | Merge tag 'frotz-for-xyzzy' of example.com:/git/froboz.git/ | |
206 | ||
207 | Completed frotz feature | |
208 | ||
209 | * tag 'frotz-for-xyzzy' (100 commits) | |
210 | Add tests and documentation for frotz | |
211 | ... | |
212 | ------------ | |
213 | ||
214 | There is no need for the auditor to explicitly fetch the contributor's | |
215 | signature, or to even be aware of what tag(s) the contributor and integrator | |
216 | used to communicate the signature. All the required information is recorded | |
217 | as part of the merge commit. |