Gabriel Staples
Gabriel Staples

Reputation: 52449

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 [email protected] 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.

Upvotes: 43

Views: 17260

Answers (4)

Christian Stewart
Christian Stewart

Reputation: 15519

I have built a Go program sendgmailapi (MIT) which implements sending emails with git send-email using the Gmail API and Oauth2.

Downsides to using SMTP to send emails:

  • Your personal IP address is leaked
  • SPF validation fails (due to the above)
  • You have to use an app password, which is less secure.

Quick setup guide for sendgmailapi:

  1. Enable the Gmail API in Google Cloud Console.
  2. Configure the OAuth consent screen (select Internal user type).
  3. Create OAuth 2.0 credentials for a web application.
  4. Download the credentials JSON file.
  5. Set up the credentials:
    mkdir -p ~/.config/sendgmail
    chmod 0700 ~/.config/sendgmail
    mv ~/Downloads/client_secret*.json ~/.config/sendgmail/credentials.json
    chmod 0600 ~/.config/sendgmail/credentials.json
    
  6. Add your Gmail address as a test user in the OAuth consent screen.
  7. Install sendgmailapi:
    go get github.com/paralin/sendgmailapi@latest
    
  8. Setup sendgmailapi:
    sendgmailapi -setup
    
  9. Configure git to use sendgmailapi:
    git config --global sendemail.smtpServer $(go env GOPATH)/bin/sendgmailapi
    

Now you can use git send-email as usual, and it will use the Gmail API instead of SMTP.

This setup eliminates the downsides of using SMTP, such as leaking your IP address and failing SPF validation, while providing a secure and efficient way to send emails through Git.

Upvotes: 1

Riking
Riking

Reputation: 2480

Set up the sendgmail tool from Google and add it to your git config:

https://github.com/google/gmail-oauth2-tools/tree/master/go/sendgmail

go install github.com/google/gmail-oauth2-tools/go/sendgmail@latest

$(go env GOPATH)/bin/sendgmail [email protected] -setup

git config sendemail.sendmailcmd "$(go env GOPATH)/bin/sendgmail [email protected]"

Downsides: This requires you to set up your own OAuth2 app. Use Lieer instead if you don't want to do that.

Upvotes: 2

Riking
Riking

Reputation: 2480

Set up lieer and add it to your git config:

https://github.com/gauteh/lieer

sudo apt install notmuch libnotmuch5-dev git-email
cd src; git clone https://github.com/gauteh/lieer.git
pip install 
notmuch # You can ignore the tagging configuration, just need ~/.notmuch-config to exist
mkdir -p ~/.mail/account.gmail/
cd ~/.mail/account.gmail/
gmi init [email protected]
# Respond to browser OAuth2 flow

git config sendemail.sendmailcmd "gmi send -t -C $HOME/.mail/account.gmail"

Upvotes: 0

Gabriel Staples
Gabriel Staples

Reputation: 52449

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 = [email protected]
    [sendemail]
        smtpServer = smtp.gmail.com
        smtpServerPort = 587
        smtpEncryption = tls
        smtpUser = [email protected]
        # (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 [email protected].

    git send-email [email protected] 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:[email protected]%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

Upvotes: 98

Related Questions