gitgit-send-email

How to configure and use `git send-email` to work with gmail to email patches to developers


How do I configure git send-email to work with gmail?


I'd like to contribute to glibc (the GNU C Library, not to be confused with GNOME's GLib library), for instance, to update the glibc/benchtests/bench-malloc-thread.c malloc speed test benchtest, but they are old and archaic and living in the Dark Ages still where we have to submit patches through email at the command-line instead of opening a Pull Request through GitHub or GitLab. :)

See glibc's contribution instructions here: https://sourceware.org/glibc/wiki/Contribution%20checklist:

  • Create one or more patches using git format-patch
  • Use git send-email --to=libc-alpha@sourceware.org to send the patch to the list, using --cc to get the attention of specific maintainers if needed.
  • Ping at least weekly if your patch has not been reviewed yet

I've tried reading and following a bunch of resources, but none seem to be complete, namely:

  1. git: 'send-email' is not a git command. See 'git --help'
  2. https://coderwall.com/p/qcsiew/setting-up-and-using-git-send-email-with-gmail
  3. https://coderwall.com/p/dp-gka/setting-up-git-send-email-with-gmail
  4. https://git-scm.com/docs/git-send-email#_use_gmail_as_the_smtp_server
  5. https://git-scm.com/docs/git-credential
  6. https://gist.github.com/jasonkarns/4354421
  7. https://gist.github.com/winksaville/dd69a860d0d05298d1945ceff048ce46
  8. Added 8 Apr. 2023, per @mcepl in this now-deleted answer: [also incomplete] https://git-send-email.io/

Note: another project you'll need to use git send-email for in order to contribute patches is Buildroot (see here: https://buildroot.org/downloads/manual/manual.html#submitting-patches), which is used to build custom embedded Linux distributions. So, if trying to figure this out for Buildroot as well, refer to my answer.


Solution

  • Note to developers and maintainers of glibc, Buildroot, and other projects which require the use of git send-email to send patches: if I wasn't a professional developer, there's not a chance in heck I could submit a patch, even if I knew how to expertly code and had important changes to make. The barrier of entry into git, rebasing, formatting patches, configuring git send-email, etc., is just too high. Consider lowering the barrier to entry by using modern tools such as GitHub, GitLab, or BitBucket to manage your projects and accept patches, in lieu of emailed patches, email mailing lists, and git send-email. One huge success case of making this transition recently is KiCad. In 2020 they were still using emailed git patches. Now, they have migrated fully to GitLab: https://gitlab.com/kicad. Their issue reporting and management, for instance, is sooooo much easier now!: https://gitlab.com/kicad/code/kicad/-/issues. Even regular users who are non-programmers are easily able to report issues now, whereas before, KiCad was using https://launchpad.net/kicad, which was more tedious and difficult.

    At a minimum, do people a favor and please direct people to this answer to help them set up git send-email, and help keep this answer up-to-date.

    How to configure and use git send-email with gmail

    After a lot of effort, and using all of the resources from the bottom of the question together, I was able to piece together a solution from the combination of all of the sources, together. Bear with me.

    Tested on Ubuntu 20.04.

    1. Install git send-email:

      sudo apt update
      sudo apt install git-email
      

      Source: git: 'send-email' is not a git command. See 'git --help' Without the above installation, you'll see:

      git: 'send-email' is not a git command. See 'git --help'.
      
    2. Install Perl script dependencies (Perl must be already installed):

      cpan Authen::SASL MIME::Base64 Net::SMTP::SSL
      

      Source: https://coderwall.com/p/qcsiew/setting-up-and-using-git-send-email-with-gmail

    3. Configure your ~/.gitconfig file by ensuring you have this in it:

      [user]
          name = First Last
          email = my_email@gmail.com
      [sendemail]
          smtpServer = smtp.gmail.com
          smtpServerPort = 587
          smtpEncryption = tls
          smtpUser = my_email@gmail.com
          # (Optional: we'll leave this commented out and use a different way)
          # smtpPass = PASSWORD
      [credential]
          helper = store
      

      Source: a variety of places, but the only one that said to add the [credential] part (which is very important) was this: https://gist.github.com/winksaville/dd69a860d0d05298d1945ceff048ce46

    4. Configure your Google Account to have 1) 2-factor authentication (to enable app-specific passwords), and 2) an app-specific password for gmail to be used by git send-email:

      1. Configure 2-factor authentication: go here: https://myaccount.google.com/security --> scroll down to "2-Step Verification" and follow the process to turn it on.
      2. Generate an app-specific password for gmail for git to use: go to the link just above, click on the "2-Step Verification" page (direct link: https://myaccount.google.com/signinoptions/two-step-verification), scroll down to "App passwords" and click on it. (or go here: https://myaccount.google.com/apppasswords) Select "Mail" as the app: enter image description here Select "Other (Custom name)" as the device: enter image description here
        and name it git send-email, or similar. Click the "GENERATE" button. It will pop up with a 16-digit full-access password. Write it down, withOUT the spaces in it. It is just the 16 chars.
    5. If you need to, squash your commits you'd like to email as a patch into a single commit. There are multiple squash techniques, but here is one common way:

      # Squash all commits from `my_first_commit` to `HEAD` (the latest commit),
      # inclusive. 
      git rebase -i my_first_commit~  # do NOT forget the tilde (~) at the end!
      # In the git editor that opens up, manually set the first entry to 
      # "pick", and set all others afterwards to "squash", or just "s" for short.
      # Save, then close the editor and let it squash.
      

      For other squash techniques, see my personal notes document, git & Linux cmds, help, tips & tricks - Gabriel.txt, in my eRCaGuy_dotfiles repo. Search that file for these phrases:

      1. == TWO WAYS TO SQUASH ==
      2. CONCISE SQUASH SUMMARY
      3. MORE-DETAILED REBASE AND SQUASH NOTES
    6. Create a patch file for your latest, squashed commit:

      git format-patch -1 HEAD
      

      This produces a patch file. Example: 0001-bench-malloc-thread.c-add-assert-that-malloc-is-neve.patch.

    7. Email that patch file to where it needs to go. For an initial test, let's just email it to yourself at my_email@gmail.com.

      git send-email --to=my_email@gmail.com 0001-bench-malloc-thread.c-add-assert-that-malloc-is-neve.patch
      

      Information about the email will display, then it will have this at the end:

      Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll):
      

      Type y and press Enter to send the message. The first time you ever send an email with git send-email it will prompt for your password. Use your app-specific password you generated for your Google Account above, and the email will send.

      Since you added the [credential] helper = store entry to your ~/.gitconfig file above, git will now automatically store your app-specific password for future use in a new file called ~/.git-credentials. If you open that file, you'll see a URL string with your password embedded in it in plain text. It will look like this:

      smtp://EMAIL%40gmail.com:16-DIGIT-PASSWORD@smtp.gmail.com%3a587
      

      where EMAIL is the first part of your email address, before the @ sign, and 16-DIGIT-PASSWORD is your 16-digit app-specific password you previously generated for your Google Account, above.

      Hopefully your hard drive is encrypted (you should have chosen LUKS encryption when you first installed Ubuntu, for full-disk encryption), and you are the only root user on the computer. If this is the case, this is not a security problem, since ll ~/.git-credentials shows -rw------- 1 your_username your_groupname, which means that file is not readable by anyone but you.

    8. Done! The next time you run git send-email, you will NOT have to type in your app password, since it is now saved inside ~/.git-credentials.

    References

    1. See all references at the bottom of the question, plus a lot of my own research and trial-and-error.

    See also

    1. How to apply a patch generated with git format-patch?
    2. What is the difference between git am and git apply?
      1. My answer