Updated git submodules
[docs.git] / docs / gerrit.rst
1 ############
2 Gerrit Guide
3 ############
4
5 Overview of Git and Gerrit
6 ==========================
7
8 Git is an opensource distributed version control system (dvcs) written
9 in the C language and originally developed by Linus Torvalds and others
10 to manage the Linux kernel. In Git, there is no central copy of the
11 repository. After you have cloned the repository, you have a functioning
12 copy of the source code with all the branches and tagged releases, in
13 your local repository.
14
15 Gerrit is an opensource web-based collaborative code review tool that
16 integrates with Git. It was developed at Google by Shawn Pearce. Gerrit
17 provides a framework for reviewing code commits before they are accepted
18 into the code base. Changes can be uploaded to Gerrit by any user.
19 However, the changes are not made a part of the project until a code
20 review is completed. Gerrit is also a good collaboration tool for
21 storing the conversations that occur around the code commits.
22
23 The OpenDaylight source code is hosted in a repository in Git.
24 Developers must use Gerrit to commit code to the OpenDaylight
25 repository.
26
27 .. note::
28
29    For more information on Git, see http://git-scm.com/. For more
30    information on Gerrit, see https://code.google.com/p/gerrit/.
31
32 Prerequisites
33 =============
34
35 Before you get started, you should have:
36
37 * an OpenDaylight account (sign up `here
38   <https://identity.opendaylight.org/carbon/user-registration/index.jsp?region=region1&item=user_registration_menu>`_)
39   See `Creating an OpenDaylight Account`_ below for detailed instructions.
40 * git installed (see: http://www.git-scm.com/downloads)
41 * git configured with your name, e-mail address and editor
42
43   .. code-block:: bash
44
45      git config --global user.name "Firstname Lastname"
46      git config --global user.email "email@address.com"
47      git config --global core.editor "text-editor-name"
48
49   .. note:: Your name and e-mail address (including capitalization) must match what you entered
50             when creating your OpenDaylight account.
51
52 * an ssh public/private key pair (see the good `Github docs on generating ssh keys
53   <https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/>`_)
54
55   * that is registered the OpenDaylight Gerrit server. See `Registering your SSH key with Gerrit`_
56     below for detailed instructions.
57
58 * git-review installed (see: https://www.mediawiki.org/wiki/Gerrit/git-review#Installation)
59
60
61 Setting up Each Git Repository
62 ==============================
63
64 To clone a new repository:
65
66 .. code-block:: bash
67
68    git clone https://git.opendaylight.org/gerrit/${project_short_name}
69
70 For example to clone the Documentation repository:
71
72 .. code-block:: bash
73
74    git clone https://git.opendaylight.org/gerrit/docs
75
76
77 Common Gerrit Tasks
78 ===================
79
80 The following sections describe the most common Gerrit tasks you will need to complete while
81 working with code in OpenDaylight.
82
83 Submitting a New Patch
84 ----------------------
85
86 #. On your machine, open a shell and switch to the directory with the git repository. Assuming
87    you are using the docs repository:
88
89    .. code-block:: bash
90
91       cd docs
92
93 #. To remove any dependencies on other files you are working on, check out the appropriate branch:
94
95    .. code-block:: bash
96
97       git checkout ${remote_branch_name}  # will switch to the branch
98
99    .. note:: normally, ``${remote_branch_name}`` should be master, but during a release, the
100              master will switch to ``stable/${release_name}``, e.g., ``stable/carbon`` at some
101              point. Also, if you are updating an existing release check out that branch.
102
103    .. note:: If you see an error like``error: pathspec 'stable/carbon' did not match any file(s)
104              known to git.``, try this command instead:
105
106              .. code-block:: bash
107
108                 git checkout -b ${remote_branch_name} origin/${remote_branch_name}
109
110              .. note:: This should only be necessary once.
111
112 #. Get a copy of the latest files from the server:
113
114    .. code-block:: bash
115
116       git pull                                      # will get all the changes from the server
117       git reset --hard origin/${remote_branch_name} # (optional) will undo any local changes you've
118                                                     # (accidentally) made to ${remote_branch_name}
119
120 #. Create a new branch for your work:
121
122    .. code-block:: bash
123
124       git checkout -b ${local_branch_name}
125
126    .. note:: Spaces are not allowed in ``${local_branch_name}``.
127
128 #. Create new files or edit existing files, as needed.
129 #. Commit the files you have worked on:
130
131    * If you've created any new files, run:
132
133      .. code-block:: bash
134
135         git add ${filename}
136
137    * To commit existing files you edited, run:
138
139      * ``git commit -as``
140      * Your default terminal text editor will open.
141
142        .. note:: The -as options instruct git to commit all of the files you have edited (``-a``)
143                  and sign your commit request with your email address and name (``-s``). The
144                  sign-off is to indicate that you agree with this statement::
145
146                       Developer's Certificate of Origin 1.1
147
148                          By making a contribution to this project, I certify that:
149
150                          (a) The contribution was created in whole or in part by me and I
151                              have the right to submit it under the open source license
152                              indicated in the file; or
153
154                          (b) The contribution is based upon previous work that, to the best
155                              of my knowledge, is covered under an appropriate open source
156                              license and I have the right under that license to submit that
157                              work with modifications, whether created in whole or in part
158                              by me, under the same open source license (unless I am
159                              permitted to submit under a different license), as indicated
160                              in the file; or
161
162                          (c) The contribution was provided directly to me by some other
163                              person who certified (a), (b) or (c) and I have not modified
164                              it.
165
166                          (d) I understand and agree that this project and the contribution
167                              are public and that a record of the contribution (including all
168                              personal information I submit with it, including my sign-off) is
169                              maintained indefinitely and may be redistributed consistent with
170                              this project or the open source license(s) involved.
171
172    * Add a brief description of the changes you have made to the beginning of the commit request
173      and then save the request.
174
175      .. note:: Writing good git commit messages is important and relatively easy, but it's good to
176                familiarize yourself with general guidelines like this `How to Write a Git Commit
177                Message Guide <https://chris.beams.io/posts/git-commit/>`_.
178
179      .. important:: We have linters that check for some of the style guides including that the
180                     first line of a git commit message is 50 characters or less. So, make sure to
181                     follow that one.
182
183 #. Submit your files for review:
184
185    * ``git review``
186    * You will receive 2 emails from Gerrit Code Review: The first indicating that a build to
187      incorporate your changes has started; and the second indicating whether the build was created
188      successfully.
189
190 #. Determine your patch’s change number:
191
192    * Open either of the emails you received after submitting your files for review.
193    * Locate the following line in the terminal: ``To view, visit <patch URL>``
194
195      .. note:: The number at the end of this URL is your patch’s change number. You will need
196                this in order to make updates to the patch later.
197
198 Updating an Existing Patch
199 --------------------------
200
201 #. On your machine, open a shell and switch to the directory containing the repository:
202    ``cd ${repository_name}``, e.g., ``cd docs``
203 #. Download the patch you want to update: ``git review -d ${change_number}``
204 #. | (Optional) View information on the latest changes made to that patch:
205    | To view the files that were edited, run ``git show``
206    | To view a listing of the files that were edited and the number of lines in those files that
207      were edited, run ``git show --stat``
208 #. Make the necessary changes to the patch’s files.
209 #. Commit your changes:
210
211    #. run ``git commit -a --amend``
212    #. Update the current patch description and then save the commit request.
213
214       .. note:: If you feel as though you did enough additional work on the patch that you should
215                 be mentioned, add your name in the footer with a line like ``Co-Authored-By: First
216                 Last <email>``.
217
218 #. | Submit your files for review:
219    | ``git review``
220
221 You will receive 2 emails from Gerrit Code Review: the first indicating that a build to incorporate
222 your changes has started; and the second indicating whether the build was created successfully.
223
224 Code Review
225 ===========
226
227 All contributions to OpenDaylight Git repositories use Gerrit for code review.
228
229 The code review process is meant to provide constructive feedback about a proposed change.
230 Committers and interested contributors will review the change, give their feedback, propose
231 revisions and work with the change author through iterations of the patch until it's ready to be
232 merged.
233
234 Feedback is provided and the change is managed via the Gerrit web UI.
235
236 .. figure:: images/gerrit-web-ui.png
237
238    Wide view of a change via the Gerrit web UI
239
240 Pre-review
241 ----------
242
243 Many times, change authors will want to push changes to Gerrit before they are actually ready for
244 review. This is a good practice and is encouraged. It has been the experience of Integration/* so
245 far that pushing early and often tends to reduce the amount of work overall.
246
247 .. note:: This is not required and in some projects, not encouraged, but the general idea of making
248           sure patches are ready for review when submitted is a good one.
249
250 .. note:: While in draft state, Gerrit triggers, e.g., verify Jenkins jobs, won't run by default.
251           You can trigger them despite it being a draft by adding ``jenkins-releng`` as a reviewer.
252           You may need to do a recheck by replying with a comment containing recheck to trigger the
253           jobs after adding the reviewer.
254
255 To mark an uploaded change as not ready for attention by committers and interested contributors (in
256 order of preference), either mark the Gerrit a draft (by adding a ``-D`` to your ``git review``
257 command), vote -1 on it yourself or modify the commit message with "WIP" ("Work in Progress").
258
259 Don't add committers to the Reviewers list for a change while it's in the pre-review state, as it
260 adds noise to their review queue.
261
262 Review
263 ------
264
265 Once an author wants a change to be reviewed, they need to take some actions to put it on the radar
266 of the committers.
267
268 If the change is marked as a draft, you'll need to publish it. This can be done from the Gerrit web
269 UI.
270
271 .. figure:: images/gerrit-publish-button.png
272
273    Gerrit Web UI button to publish a draft change.
274
275 Remove your -1 vote if you've marked it with one. If you think the patch is ready to be merged,
276 vote +1. If there isn't an automated job to test your change and vote +1/-1 for Verified, you'll
277 need to do as much testing yourself as possible and then manually vote +1 to Verified. You can
278 also vote +1 for Verified if you've done testing in addition to any automated tests. Describing
279 the testing you did or didn't do is typically helpful.
280
281 .. figure:: images/gerrit-voting-interface.png
282
283    Gerrit voting interface, exposed by the Reply button.
284
285 Once the change is published and you've voted for it to be merged, add the people who need to
286 review/merge the change to the Gerrit Reviewers list. For Integration/Packaging, add all of our
287 committers (Daniel Farrell, Jamo Luhrsen, Thanh Ha) in addition to any other relevant contributors.
288 The auto-complete for this Gerrit UI field is somewhat flaky, but typing the full name from the
289 start typically works.
290
291 .. figure:: images/gerrit-reviewers-interface.png
292
293    Gerrit Reviewers list with Int/Pack committers added
294
295 Reviewers will give feedback via Gerrit comments or inline against the diff.
296
297 .. figure:: images/gerrit-inline-feedback.png
298
299    Gerrit inline feedback about a typo
300
301 Updated versions of the proposed change should be pushed as new patchesets to the same Gerrit,
302 either by the original submitter or other contributors. Amending proposed changes owned by others
303 while reviewing may be more efficient than documenting the problem, -1ing, waiting for the original
304 submitter to make the changes, re-reviewing and merging.
305
306 Changes can be downloaded for local manipulation and then re-uploaded with updates via git-review.
307 See `Updating an Existing Patch`_ above. Once you have re-uploaded the patch the Gerrit web UI for
308 the proposed change will reflect the new patcheset.
309
310 .. figure:: images/gerrit-patch-update-history.png
311
312    Gerrit history showing a patch update
313
314 Reviewers will use the diff between the last time time they gave review and the current patchset
315 to quickly understand updates, speeding the code review process.
316
317 .. figure:: images/gerrit-diff-menu.png
318
319    Gerrit diff menu
320
321 Iterative feedback continues until consensus is reached (typically: all active reviewers +1/+2 and
322 no -1s, definitely no -2s), at least one committer +2s and a committer merges the change.
323
324 .. figure:: images/gerrit-code-review-votes.png
325
326    Gerrit code review votes
327
328 Merge
329 -----
330
331 Once a patch has gotten a +2 from a committer and they have clicked the submit button the project's
332 merge job should run and publish the project's artifacts to Nexus. Once this is done other projects
333 will be able to see the results of that patch.
334
335 This is particularly important when merging dependent patches across multiple projects. You will
336 need to wait for the merge job to run on one patch before any patches in other projects depending
337 on it will successful verify.
338
339 Setting up Gerrit
340 =================
341
342 Creating an OpenDaylight Account
343 --------------------------------
344
345 #. Using a Google Chrome or Mozilla Firefox browser, go to
346    https://git.opendaylight.org/gerrit
347
348    The main page shows existing Gerrit requests. These are patches that
349    have been pushed to the repository and not yet verified, reviewed, and
350    merged.
351
352    .. note::
353
354       If you already have an OpenDaylight account, you can click **Sign
355       In** in the top right corner of the page and follow the instructions
356       to enter the OpenDaylight page.
357
358    .. figure:: images/gerrit-sign-in.jpg
359       :alt: Signing in to OpenDaylight account
360
361       Signing in to OpenDaylight account
362
363 #. If you do not have an existing OpenDaylight account, click **Account
364    signup/management** on the top bar of the main Gerrit page.
365
366    The **WS02 Identity Server** page is displayed.
367
368    .. figure:: images/gerrit-setup.jpg
369       :alt: Gerrit Account signup/management link
370
371       Gerrit Account signup/management link
372
373 #. In the **WS02 Identity Server** page, click **Sign-up** in the left
374    pane.
375
376    There is also an option to authenticate your sign in with OpenID. This
377    option is not described in this document.
378
379    .. figure:: images/gerrit-sign-up.jpg
380       :alt: Sign-up link for Gerrit account
381
382       Sign-up link for Gerrit account
383
384 #. Click on the **Sign-up with User Name/Password** image on the right
385    pane to continue to the actual sign-up page.
386
387    .. figure:: images/gerrit-signup-image.jpg
388       :alt: Sign-up with User Name/Password Image
389
390       Sign-up with User Name/Password Image
391
392 #. Fill out the details in the account creation form and then click
393    **Submit**.
394
395    .. figure:: images/gerrit-form-details.jpg
396       :alt: Filling out the details
397
398       Filling out the details
399
400 You now have an OpenDaylight account that can be used with Gerrit to
401 pull the OpenDaylight code.
402
403 Generating SSH keys for your system
404 -----------------------------------
405
406 You must have SSH keys for your system to register with your Gerrit
407 account. The method for generating SSH keys is different for different
408 types of operating systems.
409
410 The key you register with Gerrit must be identical to the one you will
411 use later to pull or edit the code. For example, if you have a
412 development VM which has a different UID login and keygen than that of
413 your laptop, the SSH key you generate for the VM is different from the
414 laptop. If you register the SSH key generated on your VM with Gerrit and
415 do not reuse it on your laptop when using Git on the laptop, the pull
416 fails.
417
418 .. note::
419
420     For more information on SSH keys for Ubuntu, see
421     https://help.ubuntu.com/community/SSH/OpenSSH/Keys. For generating
422     SSH keys for Windows, see
423     https://help.github.com/articles/generating-ssh-keys.
424
425 For a system running Ubuntu operating system, follow the steps below:
426
427 #. Run the following command::
428
429       mkdir ~/.ssh
430       chmod 700 ~/.ssh
431       ssh-keygen -t rsa
432
433 #. You are prompted for a location to save the keys, and a passphrase
434    for the keys.
435
436    This passphrase protects your private key while it is stored on the hard
437    drive. You must use the passphrase to use the keys every time you need
438    to login to a key-based system::
439
440       Generating public/private rsa key pair.
441       Enter file in which to save the key (/home/b/.ssh/id_rsa):
442       Enter passphrase (empty for no passphrase):
443       Enter same passphrase again:
444       Your identification has been saved in /home/b/.ssh/id_rsa.
445       Your public key has been saved in /home/b/.ssh/id_rsa.pub.
446
447 Your public key is now available as **.ssh/id\_rsa.pub** in your home
448 folder.
449
450 Registering your SSH key with Gerrit
451 ------------------------------------
452
453 #. Using a Google Chrome or Mozilla Firefox browser, go to
454    https://git.opendaylight.org/gerrit.
455
456 #. Click **Sign In** to access the OpenDaylight repository.
457
458    .. figure:: images/gerrit-sign-in.jpg
459       :alt: Signin in to OpenDaylight repository
460
461       Signin in to OpenDaylight repository
462
463 #. Click your name in the top right corner of the window and then click
464    **Settings**.
465
466    The **Settings** page is displayed.
467
468    .. figure:: images/gerrit-settings.jpg
469       :alt: Settings page for your Gerrit account
470
471       Settings page for your Gerrit account
472
473 #. Click **SSH Public Keys** under **Settings**.
474
475 #. Click **Add Key**.
476
477 #. In the **Add SSH Public Key** text box, paste the contents of your
478    **id\_rsa.pub** file and then click **Add**.
479
480    .. figure:: images/gerrit-ssh-keys.jpg
481       :alt: Adding your SSH key
482
483       Adding your SSH key
484
485 To verify your SSH key is working correctly, try using an SSH client to
486 connect to Gerrit’s SSHD port::
487
488     $ ssh -p 29418 <sshusername>@git.opendaylight.org
489     Enter passphrase for key '/home/cisco/.ssh/id_rsa':
490     ****    Welcome to Gerrit Code Review    ****
491     Hi <user>, you have successfully connected over SSH.
492     Unfortunately, interactive shells are disabled.
493     To clone a hosted Git repository, use: git clone ssh://<user>@git.opendaylight.org:29418/REPOSITORY_NAME.git
494     Connection to git.opendaylight.org closed.
495
496 You can now proceed to either Pulling, Hacking, and Pushing the Code
497 from the CLI or Pulling, Hacking, and Pushing the Code from Eclipse
498 depending on your implementation.
499
500 Using https to push to Gerrit
501 =============================
502
503 It is highly recommended to use ssh to push to Gerrit. In the event that you cannot use ssh, e.g.,
504 a corporate firewall is blocking blocking you, then falling back to pushing via https should work.
505
506 Gerrit does not allow you to use your regular account credentials when pushing
507 via https. Instead it requires you to first generate a http password via the Gerrit
508 Web UI and use that as the password when pushing via https.
509
510 .. figure:: images/gerrit-https-password-setup.png
511
512    Setting up an https password to push using https instead of ssh.
513
514 To do this:
515
516 #. navigate to https://git.opendaylight.org/gerrit/#/settings/http-password
517    (Steps 1, 2 and 3 in the image above.)
518 #. click the **Generate Password** button.
519
520 Gerrit will then generate a random password which you will need to use as your
521 password when using Git to push code to Gerrit via https.
522
523 To push using git over https, do the following
524
525 .. code-block:: bash
526
527    git remote add https https://git.opendaylight.org/gerrit/p/${repo_name}  # adds an https version of the git server
528    git push https HEAD:refs/for/${branch_name}                        # will ask you for your username and password
529                                                                       #   ${branch_name} should usually be master,
530                                                                       #   but can be stable/carbon or something else
531
532 Signing Gerrit Commits
533 ======================
534
535 1. Generate your GPG key.
536
537    The following instructions work on a Mac, but the general approach
538    should be the same on other OSes.
539
540    .. code-block:: bash
541
542       brew install gpg2  # If you don't have homebrew, get that here: http://brew.sh/
543       gpg2 --gen-key
544       # pick 1 for "RSA and RSA"
545       # enter 4096 to creat a 4096-bit key
546       # enter an expiration time, I picked 2y for 2 years
547       # enter y to accept the expiration time
548       # pick O or Q to accept your name/email/comment
549       # enter a pass phrase twice. it seems like backspace doesn't work, so type carefully
550       gpg2 --fingerprint
551       # you'll get something like this:
552       # spectre:~ ckd$ gpg2 --fingerprint
553       # /Users/ckd/.gnupg/pubring.gpg
554       # -----------------------------
555       # pub   4096R/F566C9B1 2015-04-06 [expires: 2017-04-05]
556       #       Key fingerprint = 7C37 02AC D651 1FA7 9209  48D3 5DD5 0C4B F566 C9B1
557       # uid       [ultimate] Colin Dixon <colin at colindixon.com>
558       # sub   4096R/DC1497E1 2015-04-06 [expires: 2017-04-05]
559       # you're looking for the part after 4096R, which is your key ID
560       gpg2 --send-keys $KEY_ID
561       # in the above example, the $KEY_ID would be F566C9B1
562       # you should see output like this:
563       # gpg: sending key F566C9B1 to hkp server keys.gnupg.net
564
565    If you're trying to participate in an OpenDaylight keysigning, then
566    send the output of ``gpg2 --fingerprint $KEY_ID`` to
567    keysigning@opendaylight.org
568
569    .. code-block:: bash
570
571       gpg2 --fingerprint $KEY_ID
572       # in the above example, the $KEY_ID would be F566C9B1
573       # in my case, the output was:
574       # pub   4096R/F566C9B1 2015-04-06 [expires: 2017-04-05]
575       #       Key fingerprint = 7C37 02AC D651 1FA7 9209  48D3 5DD5 0C4B F566 C9B1
576       # uid       [ultimate] Colin Dixon <colin at colindixon.com>
577       # sub   4096R/DC1497E1 2015-04-06 [expires: 2017-04-05]
578
579 2. Install gpg, instead of or addition to gpg2. It appears as though
580    gpg2 has annoying things that it does when asking for your
581    passphrase, which I haven't debugged yet.
582
583    .. note:: you can tell Git to use gpg by doing:
584      ``git config --global gpg.program gpg2``
585      but that then will seem to struggle asking for your
586      passphrase unless you have your gpg-agent set up right.
587
588 3. Add you GPG to Gerrit
589
590    a. Run the following at the CLI:
591
592       .. code-block:: bash
593
594          gpg --export -a $FINGER_PRINT
595          # e.g., gpg --export -a F566C9B1
596          # in my case the output looked like:
597          # -----BEGIN PGP PUBLIC KEY BLOCK-----
598          # Version: GnuPG v2
599          #
600          # mQINBFUisGABEAC/DkcjNUhxQkRLdfbfdlq9NlfDusWri0cXLVz4YN1cTUTF5HiW
601          # ...
602          # gJT+FwDvCGgaE+JGlmXgjv0WSd4f9cNXkgYqfb6mpji0F3TF2HXXiVPqbwJ1V3I2
603          # NA+l+/koCW0aMReK
604          # =A/ql
605          # -----END PGP PUBLIC KEY BLOCK-----
606
607    b. Browse to https://git.opendaylight.org/gerrit/#/settings/gpg-keys
608    c. Click Add Key...
609    d. Copy the output from the above command, paste it into the box,
610       and click Add
611
612 4. Set up your Git to sign commits and push signatures
613
614    .. code-block:: bash
615
616       git config commit.gpgsign true
617       git config push.gpgsign true
618       git config user.signingkey $FINGER_PRINT
619       # e.g., git config user.signingkey F566C9B1
620
621    .. note:: you can do this instead with ``git commit -S``
622       You can use ``git commit -S`` and ``git push --signed``
623       on the CLI instead of configuring it in config if you
624       want to control which commits use your signature.
625
626 5. Commit and push a change
627
628    a. change a file
629    b. ``git commit -asm "test commit"``
630
631       .. note:: this should result in Git asking you for your passphrase
632
633    c. ``git review``
634
635       .. note:: this should result in Git asking you for your passphrase
636
637       .. note:: annoyingly, the presence of a gpgp signature or pushing
638         of a gpg signature isn't recognized as a "change" by
639         Gerrit, so if you forget to do either, you need to change
640         something about the commit to get Gerrit to accept the
641         patch again. Slightly tweaking the commit message is a
642         good way.
643
644       .. note:: this assumes you have git review set up and push.gpgsign
645         set to true. Otherwise:
646
647         ``git push --signed gerrit HEAD:refs/for/master``
648
649         .. note:: this assumes you have your gerrit remote set up, if
650             not it's something like:
651             ``ssh://ckd@git.opendaylight.org:29418/<repo>.git``
652             where repo is something like docs or controller
653
654 6. Verify that your commit is signed by going to the change in Gerrit
655    and checking for a green check (instead of a blue ?) next to your
656    name.
657
658
659 Setting up gpg-agent on a Mac
660 -----------------------------
661
662 #. Install ``gpg-agent`` and ``pinentry-mac`` using ``brew``::
663
664       brew install gpg-agent pinentry-mac
665
666 #. Edit your ``~/.gnupg/gpg.conf`` contain the line::
667
668       use-agent
669
670 #. Edit your ``~/.gnupg/gpg-agent.conf`` to something like::
671
672       use-standard-socket
673       enable-ssh-support
674       default-cache-ttl 600
675       max-cache-ttl 7200
676       pinentry-program /usr/local/bin/pinentry-mac
677
678 #. Edit your ``.bash_profile`` or equivalent file to contain the
679    following:
680
681    .. code-block:: bash
682
683       [ -f ~/.gpg-agent-info ] && source ~/.gpg-agent-info
684       if [ -S "${GPG_AGENT_INFO%%:*}" ]; then
685         export GPG_AGENT_INFO
686       else
687         eval $( gpg-agent --daemon --write-env-file ~/.gpg-agent-info )
688       fi
689
690 #. Kill any stray ``gpg-agent`` daemons running::
691
692       sudo killall gpg-agent
693
694 #. Restart your terminal (or log in and out) to reload the your
695    ``.bash_profile`` or equivalent file
696
697 #. The next time a Git operation makes a call to gpg, it should use
698    your gpg-agent to run a GUI window to ask for your passphrase and
699    give you an option to save your passphrase in the keychain.
700
701    .. figure:: images/pinentry-mac.png