Tuesday, December 20, 2011

"Pulling signed tag" is already in use in the field

[update: with finishing touches, this will be part of 1.7.9 release]

One of the more important features we wanted to have for the next release of Git (1.7.9) is to support a workflow where a pull request for a signed tag is sent to the integrator and git pull in response to the request automatically verifies the GPG signature embedded in the signed tag. See this for the background.

Earlier, a typical pull request was for a branch name in the publishing repository of a contributor, and worse yet, the default request message created by the git request-pull command did not even mention what commit to expect as the result of a requested pull, which meant that it was unnecessarily hard to make sure what was pulled was genuinely what the contributor had produced for the integrator and for third-party auditors.

This feature has been cooking in the next branch of the Git project for a while, and recently graduated to the master branch to become part of the upcoming release. Linus has been using the in-development verison, and I learned that he made a commit (2240a7b (Merge tag 'tytso-for-linus-20111214' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4, 2011-12-14)) that pulls a signed tag in response to a pull request from Ted several days ago already!

It always is satisfying to see that the result of our hard work is used in the field.

The workflow between the contributor (or a lieutenant) and the integrator looks like this:


After preparing the work to be pulled, use "git tag -s" to create a signed tag.

$ git checkout work
$ ... "git pull" from sublieutenants, "git commit" your own work ...
$ git tag -s -m "Completed frotz feature" frotz-for-linus work

And push the tag out to your publishing repository. You do not have to push your work branch or anything else.

$ R=example.com:/git/froboz.git/
$ git push $R frotz-for-linus

Then prepare a pull request message.

$ git request-pull v3.2 $R frotz-for-linus >msg.txt

The arguments are
  1. the version of the integrator's commit you based your work on;
  2. the URL of the repository, to which you have pushed what you want to get pulled; and
  3. the name of the tag you want to get pulled (earlier, you could only write branch names here).
The resulting msg.txt file should begin like so:

The following changes since commit 703f05ad5835cff92b12c29aecf8d724c8c847e2:

  Froboz 3.2 (2011-09-30 14:20:57 -0700)

are available in the git repository at:

  example.com:/git/froboz.git/ frotz-for-linus

for you to fetch changes up to 406da7803217998ff6bf5dc69c55b1613556c2f4:

  Add tests and documentation for frotz (2011-12-02 10:02:52 -0800)


Completed frotz feature

A U Thor (7):
      frotz: do not use --index in the short usage output
      frotz: Add tests and documentation for frotz


The signed tag message is shown prominently between the dashed lines before the short-log, so you may want to justify why pulling your work is worthwhile when creating the signed tag.

Then open your favorite mailer, read msg.txt in, edit and send it to your integrator.


After seeing such a pull request message, fetch and integrate the tag named in the request.

$ git pull example.com:/git/froboz.git/ frotz-for-linus

It will always open an editor to allow the integrator to fine tune the commit log message for the merge when merging a signed tag. In the editor, the integrator will see something like this:

Merge tag 'frotz-for-linus' of example.com:/git/froboz.git/

Completed frotz feature
# gpg: Signature made Fri 02 Dec 2011 10:03:01 AM PST using RSA key ID 96AFE6CB
# gpg: Good signature from "A U Thor <author@example.com>"

provided if the signature in the signed tag verifies correctly. As usual, the lines commented with # are stripped out. The resulting commit records the contents of the signed tag in a hidden field so that it can be used by others to audit in the future, so the integrator does not have to keep a separate copy of the tag in his repository (i.e. "git tag -l" won't list frotz-for-linus tag in the above example).

After the integrator responds to the pull request and the work becomes part of the permanent history, the contributor can remove the tag from the publishing repository if he or she chooses to in order to keep the tag namespace clean.


$ git push example.com :refs/tags/frotz-for-linus


Unknown said...

What if i want to look at the details of pull request by doing git fetch. That does seem to work with tag. ie, i can't do git fetch example.com:/git/froboz.git/ frotz-for-linus

_ said...

If you want to fetch, do fetch, and everything should work as expected. Hints:

$ git fetch $there v3.2
$ git cat-file -t FETCH_HEAD
$ git merge FETCH_HEAD

_ said...

Oh, of course, you would need a recent version of Git to do all of the above. Half of the work in the pull-signed-tag topic was to allow fetching a tag and keep it wrapped as a tag, instead of immediately dereferencing as a commit as older versions of Git used to.