git send-email poast
This commit is contained in:
parent
f6444034c3
commit
06091bbbb3
6 changed files with 175 additions and 23 deletions
131
content/posts/oh-no-git-send-email/index.md
Normal file
131
content/posts/oh-no-git-send-email/index.md
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
+++
|
||||||
|
date = "2022-04-22"
|
||||||
|
draft = false
|
||||||
|
path = "/blog/oh-no-git-send-email"
|
||||||
|
tags = ["git", "tools"]
|
||||||
|
title = "Oh no, `git send-email`"
|
||||||
|
+++
|
||||||
|
|
||||||
|
Say you have to contribute to some boomer project that doesn't believe in
|
||||||
|
GitHub or GitLab or Gitea or <...> which would allow for just pushing some
|
||||||
|
changes and filing a pull request. Instead, they want an *email*. Gross.
|
||||||
|
|
||||||
|
For those who are unfamiliar with the email-patch infrastructure, git is
|
||||||
|
*extremely* picky about emails being the exact format it likes and not getting
|
||||||
|
modified at all by the client. This means that in practice, you need to send
|
||||||
|
your patch emails using `git send-email` as your email client.
|
||||||
|
|
||||||
|
The patch-emailing features of git are some of its most infamous for poor
|
||||||
|
usability, which is saying something, because git as a whole is known for being
|
||||||
|
hard to use.
|
||||||
|
|
||||||
|
Theoretically, <https://git-send-email.io/> (by someone who made their own git
|
||||||
|
source hosting service that strangely uses emails to submit patches) will tell
|
||||||
|
you how to set it up. Well, except if `git send-email` has other ideas: it
|
||||||
|
would not send through my email provider for reasons that must have been a bug:
|
||||||
|
I seem to recall it was something to do with either a TLS or SMTP
|
||||||
|
implementation being broken.
|
||||||
|
|
||||||
|
I ended up needing to use a separate *Mail Transfer Agent* (SMTP-speak for
|
||||||
|
"SMTP client") and plumb it into git. For this, I used `msmtp`.
|
||||||
|
|
||||||
|
{% codesample(desc="`~/.msmtprc`") %}
|
||||||
|
# Used to identify which account you are using in the msmtp command line
|
||||||
|
account myaccountname
|
||||||
|
|
||||||
|
# Tunneled-TLS email configuration. Probably correct for most modern servers,
|
||||||
|
# but check your email provider documentation. This is correct for migadu.
|
||||||
|
|
||||||
|
host smtp.migadu.com
|
||||||
|
port 465
|
||||||
|
tls on
|
||||||
|
tls_starttls off
|
||||||
|
auth on
|
||||||
|
user user@example.com
|
||||||
|
|
||||||
|
# From address on the envelope. Probably your email, but not necessarily
|
||||||
|
# (note that this is distinct from the "from" address in the message body that
|
||||||
|
# will be shown to recipients. it needs to match the address subscribed to the
|
||||||
|
# mailing list)
|
||||||
|
from listsubscriber@example.com
|
||||||
|
|
||||||
|
# Use kwallet-query to get the password because kwallet does not support the
|
||||||
|
# freedesktop secrets protocol
|
||||||
|
# "mail" is the folder on the left hand side of the "Wallet Manager"
|
||||||
|
# and user@example.com is the name of the item
|
||||||
|
passwordeval kwallet-query -r user@example.com kdewallet -f mail
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
Then configure git (I keep this in `~/.gitconfig` as I don't really want to
|
||||||
|
check it in for spam reasons, whereas most of my git config is checked in and
|
||||||
|
stored at `~/.config/git/config`):
|
||||||
|
|
||||||
|
{% codesample(desc="`~/.gitconfig`") %}
|
||||||
|
[sendemail]
|
||||||
|
sendmailcmd = /usr/bin/msmtp
|
||||||
|
smtpserveroption = -a
|
||||||
|
smtpserveroption = myaccountname
|
||||||
|
confirm = always
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
Finally, you can send an email:
|
||||||
|
|
||||||
|
```
|
||||||
|
/tmp/nya » git init
|
||||||
|
Initialized empty Git repository in /tmp/nya/.git/
|
||||||
|
|
||||||
|
/tmp/nya - [main] » echo nyaa > README.md
|
||||||
|
/tmp/nya - [main●] » git add -A
|
||||||
|
/tmp/nya - [main●] » git commit -m 'initial commit'
|
||||||
|
[main (root-commit) 5e2e44d] initial commit
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
create mode 100644 README.md
|
||||||
|
|
||||||
|
/tmp/nya - [main] » echo nyaaaaaaaaaaaaaaaaaaaaa >> README.md
|
||||||
|
|
||||||
|
/tmp/nya - [main●] » git commit -am 'more nya'
|
||||||
|
[main 3df1f2d] more nya
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
# NOTE: you probably want to use --compose to write a message to include with
|
||||||
|
# your patch. You can also use --dry-run to do a dry run.
|
||||||
|
/tmp/nya - [main] » git send-email --to='somepoorsoul@example.com' --from=message-from@example.com HEAD^
|
||||||
|
|
||||||
|
/tmp/jade/jKCO7nnORw/0001-more-nya.patch
|
||||||
|
(mbox) Adding cc: Jade Lovelace <commitauthor@example.com> from line 'From: Jade Lovelace <commitauthor@example.com>'
|
||||||
|
|
||||||
|
From: message-from@example.com
|
||||||
|
To: somepoorsoul@example.com
|
||||||
|
Cc: Jade Lovelace <commitauthor@example.com>
|
||||||
|
Subject: [PATCH] more nya
|
||||||
|
Date: Fri, 22 Apr 2022 20:45:30 -0700
|
||||||
|
Message-Id: <20220423034529.3057172-1-message-from@example.com>
|
||||||
|
X-Mailer: git-send-email 2.35.2
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): y
|
||||||
|
OK. Log says:
|
||||||
|
Sendmail: /usr/bin/msmtp -a message-from@example.com -i somepoorsoul@example.com commitauthor@example.com
|
||||||
|
From: message-from@example.com
|
||||||
|
To: somepoorsoul@example.com
|
||||||
|
Cc: Jade Lovelace <commitauthor@example.com>
|
||||||
|
Subject: [PATCH] more nya
|
||||||
|
Date: Fri, 22 Apr 2022 20:45:30 -0700
|
||||||
|
Message-Id: <20220423034529.3057172-1-message-from@example.com>
|
||||||
|
X-Mailer: git-send-email 2.35.2
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Result: OK
|
||||||
|
```
|
||||||
|
|
||||||
|
And, yes, it was received:
|
||||||
|
|
||||||
|
{% image(name="received.png", colocated=true) %}
|
||||||
|
Screenshot of the email sent by git in an email client.
|
||||||
|
|
||||||
|
It shows the patch as you'd see with the output of format-patch.
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
See? That was ~~sooooo easy~~ very hard for no reason.
|
||||||
BIN
content/posts/oh-no-git-send-email/received.png
Normal file
BIN
content/posts/oh-no-git-send-email/received.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
|
|
@ -7,7 +7,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<article class="homepage-article" typeof="BlogPosting" resource="{{ page.permalink | safe }}">
|
<article class="homepage-article" typeof="BlogPosting" resource="{{ page.permalink | safe }}">
|
||||||
<a class="homepage-link" href="{{ page.permalink | safe }}">
|
<a class="homepage-link" href="{{ page.permalink | safe }}">
|
||||||
<h2 property="headline">{{ page.title }}</h2>
|
<h2 property="headline">{{ page.title | markdown(inline=true) | safe }}</h2>
|
||||||
</a>
|
</a>
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<span property="datePublished"
|
<span property="datePublished"
|
||||||
|
|
|
||||||
32
templates/macros/image.html
Normal file
32
templates/macros/image.html
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
{%- import "macros/colocated_asset.html" as colocated_asset -%}
|
||||||
|
|
||||||
|
{%- macro image(name, alt, colocated, height) -%}
|
||||||
|
{%- set name_sanitized = name | replace(from=".", to="-") | replace(from="/", to="-") -%}
|
||||||
|
{%- set image_id = "image" ~ name_sanitized -%}
|
||||||
|
|
||||||
|
{%- if colocated == true -%}
|
||||||
|
{%- set image_path = colocated_asset::colocated_asset(path=name) -%}
|
||||||
|
{%- set image_url = name -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set image_path = "/static/images/" ~ name -%}
|
||||||
|
{%- set image_url = get_url(path=image_path) -%}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{%- set image = resize_image(path=image_path, width=800, height=height, op="fit") -%}
|
||||||
|
<div class="image">
|
||||||
|
<a href="{{ image_url }}">
|
||||||
|
<img src="{{ image.url }}"
|
||||||
|
alt="{{ alt }}"
|
||||||
|
title="{{ alt }}"
|
||||||
|
{% if label %}
|
||||||
|
aria-describedby="{{ image_id }}"
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
{% if label %}
|
||||||
|
<span class="image-label" id="{{ image_id }}">
|
||||||
|
{{ label }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{%- endmacro image -%}
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="post" typeof="BlogPosting">
|
<div class="post" typeof="BlogPosting">
|
||||||
<header class="page-header">
|
<header class="page-header">
|
||||||
<h1 property="headline">{{ page.title }}</h1>
|
<h1 property="headline">{{ page.title | markdown(inline=true) | safe }}</h1>
|
||||||
|
|
||||||
{% if not page.extra.isPage %}
|
{% if not page.extra.isPage %}
|
||||||
<div class="detail page-detail">
|
<div class="detail page-detail">
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,9 @@
|
||||||
{% set name_sanitized = name | replace(from=".", to="-") | replace(from="/", to="-") %}
|
{%- import "macros/image.html" as image -%}
|
||||||
{% set image_id = "image" ~ name_sanitized %}
|
|
||||||
{% set alt = alt | default(value=body) %}
|
{{ image::image(
|
||||||
{% set height = height | default(value=600) %}
|
name=name,
|
||||||
<div class="image">
|
colocated=colocated | default(value=false),
|
||||||
<a href="{{ get_url(path="images/" ~ name) }}">
|
alt=alt | default(value=body),
|
||||||
<img src="{{ resize_image(path="../static/images/" ~ name, width=800, height=height, op="fit") }}"
|
height=height | default(value=600)
|
||||||
alt="{{ alt }}"
|
) }}
|
||||||
title="{{ alt }}"
|
|
||||||
{% if label %}
|
|
||||||
aria-describedby="{{ image_id }}"
|
|
||||||
{% endif %}
|
|
||||||
>
|
|
||||||
</a>
|
|
||||||
{% if label %}
|
|
||||||
<span class="image-label" id="{{ image_id }}">
|
|
||||||
{{ label }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue