From: "SZEDER Gábor" <szeder.dev@gmail.com>
To: graysongordon-gl <graysongordon1@gmail.com>, ps@pks.im
Cc: git@vger.kernel.org, gitster@pobox.com, peff@peff.net, avarab@gmail.com
Subject: Re: [PATCH v7] http: add http.sslVerifyStatus to check stapled OCSP responses
Date: Wed, 23 Sep 2026 23:07:40 +0200 [thread overview]
Message-ID: <arQ/nOH+o3XwQFD/@szeder.dev> (raw)
In-Reply-To: <20260915162348.97792-1-ggordon@gitlab.com>
On Tue, Sep 15, 2026 at 12:23:48PM -0400, graysongordon-gl wrote:
> From: Grayson Gordon <graysongordon1@gmail.com>
>
> git never sets CURLOPT_SSL_VERIFYSTATUS, so libcurl never requests the
> OCSP "Certificate Status Request" extension and any stapled response a
> server sends is ignored, including responses that explicitly state the
> certificate has been revoked.
>
> Add an http.sslVerifyStatus boolean that maps to
> CURLOPT_SSL_VERIFYSTATUS. http_options() is already the collect_fn for a
> urlmatch config, so the per-URL form works with no changes:
>
> git config http.https://example.com/.sslVerifyStatus true
>
> Defaults to false/"off". This is due to the nature of the OCSP protocol.
> If enabled, git would expect to receive OCSP stapled responses. If the
> stapled responses were not present, the connection would be blocked as
> the status of the server's certificate could not be verified. This would
> break connections to legitimate services that don't use OCSP as their
> certificate revocation mechanism.
>
> If the backend can't check the staple, curl_easy_setopt() returns
> CURLE_NOT_BUILT_IN. The error message includes curl_easy_strerror()
> along with the option name, so a libcurl built without status
> verification is easy to identify.
>
> CURLOPT_SSL_VERIFYSTATUS has existed since libcurl 7.41.0, below our
> 7.61.0 floor, so no version guard is needed.
>
> The tests that need no OCSP infrastructure stay in t5551, which t5559
> runs over https. The rest need a certificate authority, a responder to
> answer for it and a server configured to staple, so lib-httpd gains an
> opt-in LIB_HTTPD_OCSP mode and t5585 uses it to check that a "good"
> staple is accepted, a "revoked" one is refused, and that the revoked one
> is ignored when the option is off.
>
> Signed-off-by: Grayson Gordon <graysongordon1@gmail.com>
> ---
This patch was merged to 'next' the other day, and the last test in
the new t5585 fails on my system.
> diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
> index 115455784c..554b0e44fa 100644
> --- a/t/lib-httpd.sh
> +++ b/t/lib-httpd.sh
> @@ -25,6 +25,7 @@
> # LIB_HTTPD_DAV enable DAV
> # LIB_HTTPD_SVN enable SVN at given location (e.g. "svn")
> # LIB_HTTPD_SSL enable SSL
> +# LIB_HTTPD_OCSP enable OCSP stapling
> # LIB_HTTPD_PROXY enable proxy
> #
> # Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
> @@ -183,15 +184,26 @@ prepare_httpd() {
>
> ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
>
> + if test -n "$LIB_HTTPD_OCSP"
> + then
> + LIB_HTTPD_SSL=t
> + fi
> +
> if test -n "$LIB_HTTPD_SSL"
> then
> HTTPD_PROTO=https
>
> - RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \
> - -config "$TEST_PATH/ssl.cnf" \
> - -new -x509 -nodes \
> - -out "$HTTPD_ROOT_PATH/httpd.pem" \
> - -keyout "$HTTPD_ROOT_PATH/httpd.pem"
> + if test -n "$LIB_HTTPD_OCSP"
> + then
> + prepare_ocsp_stapling
> + HTTPD_PARA="$HTTPD_PARA -DOCSP"
> + else
> + RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \
> + -config "$TEST_PATH/ssl.cnf" \
> + -new -x509 -nodes \
> + -out "$HTTPD_ROOT_PATH/httpd.pem" \
> + -keyout "$HTTPD_ROOT_PATH/httpd.pem"
> + fi
> GIT_SSL_NO_VERIFY=t
> export GIT_SSL_NO_VERIFY
> HTTPD_PARA="$HTTPD_PARA -DSSL"
> @@ -262,6 +274,114 @@ stop_httpd() {
> -f "$TEST_PATH/apache.conf" $HTTPD_PARA -k stop
> }
>
> +restart_httpd () {
> + httpd_pid=$(cat "$HTTPD_ROOT_PATH/httpd.pid") &&
> + stop_httpd &&
> + while kill -0 "$httpd_pid" 2>/dev/null
> + do
> + sleep 1
> + done &&
> + "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
> + -f "$TEST_PATH/apache.conf" $HTTPD_PARA \
> + -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start
> +}
> +
> +# Check if the linked libcurl can verify stapled OCSP responses.
> +test_lazy_prereq SSL_VERIFYSTATUS '
> + test "$HTTPD_PROTO" = "https" &&
> + test_might_fail git -c http.sslVerifyStatus=true \
> + ls-remote "$HTTPD_URL" 2>err &&
> + ! grep "http.sslVerifyStatus is set" err
> +'
When checking this prereq in t5585, I get the following trace:
mkdir -p "$TRASH_DIRECTORY/prereq-test-dir-SSL_VERIFYSTATUS" &&
(
cd "$TRASH_DIRECTORY/prereq-test-dir-SSL_VERIFYSTATUS" &&
test "$HTTPD_PROTO" = "https" &&
test_might_fail git -c http.sslVerifyStatus=true \
ls-remote "$HTTPD_URL" 2>err &&
cat err && # debug
! grep "http.sslVerifyStatus is set" err
)
+ mkdir -p /home/szeder/src/git/t/trash directory.t5585-http-ssl-ocsp/prereq-test-dir-SSL_VERIFYSTATUS
+ cd /home/szeder/src/git/t/trash directory.t5585-http-ssl-ocsp/prereq-test-dir-SSL_VERIFYSTATUS
+ test https = https
+ test_might_fail git -c http.sslVerifyStatus=true ls-remote https://127.0.0.1:5585
+ cat err
fatal: repository 'https://127.0.0.1:5585/' not found
+ grep http.sslVerifyStatus is set err
prerequisite SSL_VERIFYSTATUS ok
I added that 'cat err' to see the error message. Turns out that 'git
ls-remote' can't even find the repository on the remote, but the
prereq is still considered fulfilled. Is that right?
In t5559 I get the following trace:
+ mkdir -p /home/szeder/src/git/t/trash directory.t5559-http-fetch-smart-http2/prereq-test-dir-SSL_VERIFYSTATUS
+ cd /home/szeder/src/git/t/trash directory.t5559-http-fetch-smart-http2/prereq-test-dir-SSL_VERIFYSTATUS
+ test https = https
+ test_might_fail git -c http.sslVerifyStatus=true ls-remote https://127.0.0.1:5559
+ cat err
fatal: unable to access 'https://127.0.0.1:5559/': No OCSP response received
+ grep http.sslVerifyStatus is set err
prerequisite SSL_VERIFYSTATUS ok
This time the error message talks about missing OCSP response, but the
prereq is still considered fulfilled. Again: is that right?!
Instead of the lack of a certain string in the error message, is
there something positive that we can test instead?
> +# Set up a certificate authority. It issues certificate "httpd.pem"
> +# and is able to revoke it. Used instead of the self-signed
> +# certificate when LIB_HTTPD_OCSP is set.
> +prepare_ocsp_stapling () {
> + LIB_HTTPD_OCSP_PORT=$((LIB_HTTPD_PORT + 10000))
> +
> + # Referenced by ocsp-ca.cnf.
> + OCSP_CA_DIR="$HTTPD_ROOT_PATH/ocsp-ca"
> + OCSP_URI="http://127.0.0.1:$LIB_HTTPD_OCSP_PORT"
> + export OCSP_CA_DIR OCSP_URI
> +
> + mkdir -p "$OCSP_CA_DIR/newcerts" &&
> + >"$OCSP_CA_DIR/index.txt" &&
> + echo 1000 >"$OCSP_CA_DIR/serial" &&
> +
> + openssl req -config "$TEST_PATH/ocsp-ca.cnf" \
> + -new -x509 -nodes -days 2 \
> + -subj "/CN=git-test-ca" -extensions v3_ca \
> + -keyout "$HTTPD_ROOT_PATH/ca.key" \
> + -out "$HTTPD_ROOT_PATH/ca.pem" &&
> + openssl req -config "$TEST_PATH/ocsp-ca.cnf" \
> + -new -nodes \
> + -subj "/CN=127.0.0.1" \
> + -keyout "$HTTPD_ROOT_PATH/httpd.key" \
> + -out "$HTTPD_ROOT_PATH/httpd.csr" &&
> + openssl ca -config "$TEST_PATH/ocsp-ca.cnf" -batch \
> + -cert "$HTTPD_ROOT_PATH/ca.pem" \
> + -keyfile "$HTTPD_ROOT_PATH/ca.key" \
> + -in "$HTTPD_ROOT_PATH/httpd.csr" \
> + -out "$HTTPD_ROOT_PATH/httpd.crt" &&
> + cat "$HTTPD_ROOT_PATH/httpd.key" "$HTTPD_ROOT_PATH/httpd.crt" \
> + >"$HTTPD_ROOT_PATH/httpd.pem"
> +}
> +
> +run_ocsp_responder () {
> + openssl ocsp -port "$LIB_HTTPD_OCSP_PORT" \
> + -index "$OCSP_CA_DIR/index.txt" \
> + -CA "$HTTPD_ROOT_PATH/ca.pem" \
> + -rsigner "$HTTPD_ROOT_PATH/ca.pem" \
> + -rkey "$HTTPD_ROOT_PATH/ca.key" \
> + -nmin 60 >>"$HTTPD_ROOT_PATH/ocsp.log" 2>&1 &
> + echo $! >"$HTTPD_ROOT_PATH/ocsp.pid"
> +
> + for i in $(test_seq 1 10)
> + do
> + if openssl ocsp -no_nonce \
> + -CAfile "$HTTPD_ROOT_PATH/ca.pem" \
> + -issuer "$HTTPD_ROOT_PATH/ca.pem" \
> + -cert "$HTTPD_ROOT_PATH/httpd.crt" \
> + -url "$OCSP_URI" >/dev/null 2>&1
> + then
> + return 0
> + fi
> + sleep 1
> + done
> + return 1
> +}
> +
> +start_ocsp_responder () {
> + test_atexit stop_ocsp_responder
> +
> + if ! run_ocsp_responder
> + then
> + cat "$HTTPD_ROOT_PATH"/ocsp.log >&4 2>/dev/null
> + test_skip_or_die GIT_TEST_HTTPD "OCSP responder setup failed"
> + fi
> +}
> +
> +stop_ocsp_responder () {
> + if test -f "$HTTPD_ROOT_PATH/ocsp.pid"
> + then
> + kill "$(cat "$HTTPD_ROOT_PATH/ocsp.pid")" 2>/dev/null
> + rm -f "$HTTPD_ROOT_PATH/ocsp.pid"
> + fi
> +}
> +
> +# Revoke the certificate used by httpd and make both the OCSP responder
> +# and httpd aware of it.
> +revoke_httpd_cert () {
> + openssl ca -config "$TEST_PATH/ocsp-ca.cnf" \
> + -cert "$HTTPD_ROOT_PATH/ca.pem" \
> + -keyfile "$HTTPD_ROOT_PATH/ca.key" \
> + -revoke "$HTTPD_ROOT_PATH/httpd.crt" &&
> + stop_ocsp_responder &&
> + run_ocsp_responder &&
> + restart_httpd
> +}
> +
> test_http_push_nonff () {
> REMOTE_REPO=$1
> LOCAL_REPO=$2
> diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
> index 4149fc1078..de5ca45bb8 100644
> --- a/t/lib-httpd/apache.conf
> +++ b/t/lib-httpd/apache.conf
> @@ -242,6 +242,22 @@ SSLSessionCache none
> SSLEngine On
> </IfDefine>
>
> +<IfDefine OCSP>
> +<IfModule !mod_socache_shmcb.c>
> + LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
> +</IfModule>
> +
> +SSLCertificateChainFile ca.pem
> +SSLUseStapling On
> +# Stapling needs a mutex, which apache would put in a system-wide
> +# runtime directory that need not be writable. Keep it in the server
> +# root, or httpd refuses to start instead of skipping the tests.
> +DefaultRuntimeDir .
> +SSLStaplingCache shmcb:ssl_stapling(65536)
> +# Staple non-"good" responses too, so clients get to see "revoked".
> +SSLStaplingReturnResponderErrors On
> +</IfDefine>
> +
> <Location /auth/>
> AuthType Basic
> AuthName "git-auth"
> diff --git a/t/lib-httpd/ocsp-ca.cnf b/t/lib-httpd/ocsp-ca.cnf
> new file mode 100644
> index 0000000000..47a58139b5
> --- /dev/null
> +++ b/t/lib-httpd/ocsp-ca.cnf
> @@ -0,0 +1,35 @@
> +[ ca ]
> +default_ca = CA_default
> +
> +[ CA_default ]
> +dir = $ENV::OCSP_CA_DIR
> +database = $dir/index.txt
> +new_certs_dir = $dir/newcerts
> +serial = $dir/serial
> +default_md = sha256
> +default_days = 2
> +policy = policy_anything
> +email_in_dn = no
> +unique_subject = no
> +x509_extensions = server_cert
> +
> +[ policy_anything ]
> +commonName = supplied
> +
> +[ req ]
> +default_bits = 2048
> +distinguished_name = req_distinguished_name
> +prompt = no
> +
> +[ req_distinguished_name ]
> +# The subject is always given on the command line via -subj.
> +
> +[ v3_ca ]
> +basicConstraints = critical, CA:TRUE
> +keyUsage = critical, digitalSignature, keyCertSign, cRLSign
> +subjectKeyIdentifier = hash
> +
> +[ server_cert ]
> +basicConstraints = CA:FALSE
> +subjectAltName = IP:127.0.0.1
> +authorityInfoAccess = OCSP;URI:$ENV::OCSP_URI
> diff --git a/t/meson.build b/t/meson.build
> index 3ca7b27104..72cbd12d8f 100644
> --- a/t/meson.build
> +++ b/t/meson.build
> @@ -728,6 +728,7 @@ integration_tests = [
> 't5582-fetch-negative-refspec.sh',
> 't5583-push-branches.sh',
> 't5584-http-429-retry.sh',
> + 't5585-http-ssl-ocsp.sh',
> 't5600-clone-fail-cleanup.sh',
> 't5601-clone.sh',
> 't5602-clone-remote-exec.sh',
> diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
> index 805bec025c..c51b14291d 100755
> --- a/t/t5551-http-fetch-smart.sh
> +++ b/t/t5551-http-fetch-smart.sh
> @@ -680,6 +680,28 @@ test_expect_success 'passing hostname resolution information works' '
> git -c "http.curloptResolve=$BOGUS_HOST:$LIB_HTTPD_PORT:127.0.0.1" ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null
> '
>
> +test_expect_success SSL_VERIFYSTATUS 'http.sslVerifyStatus=true fails without a staple' '
> + test_must_fail git -c http.sslVerifyStatus=true \
> + ls-remote "$HTTPD_URL/smart/repo.git"
Shouldn't we check the error message, to make sure that the command
failed for the expected reason (here and in t5585 as well)?
> +'
> +
> +test_expect_success SSL_VERIFYSTATUS 'http.sslVerifyStatus=false is a no-op' '
> + git -c http.sslVerifyStatus=false \
> + ls-remote "$HTTPD_URL/smart/repo.git" >actual &&
> + test_line_count -gt 0 actual
> +'
> +
> +test_expect_success SSL_VERIFYSTATUS 'per-URL sslVerifyStatus applies to a matching URL' '
> + test_must_fail git -c "http.$HTTPD_URL/.sslVerifyStatus=true" \
> + ls-remote "$HTTPD_URL/smart/repo.git"
> +'
> +
> +test_expect_success SSL_VERIFYSTATUS 'per-URL sslVerifyStatus is not applied to other URLs' '
> + git -c "http.https://example.com/.sslVerifyStatus=true" \
> + ls-remote "$HTTPD_URL/smart/repo.git" >actual &&
> + test_line_count -gt 0 actual
> +'
> +
> # here user%40host is the URL-encoded version of user@host,
> # which is our intentionally-odd username to catch parsing errors
> url_user=$HTTPD_URL_USER/auth/smart/repo.git
> diff --git a/t/t5585-http-ssl-ocsp.sh b/t/t5585-http-ssl-ocsp.sh
> new file mode 100755
> index 0000000000..0d1310215f
> --- /dev/null
> +++ b/t/t5585-http-ssl-ocsp.sh
> @@ -0,0 +1,55 @@
> +#!/bin/sh
> +
> +test_description='verification of stapled OCSP responses via http.sslVerifyStatus'
> +
> +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> +
> +. ./test-lib.sh
> +
> +LIB_HTTPD_OCSP=1
> +. "$TEST_DIRECTORY"/lib-httpd.sh
> +
> +start_httpd
> +start_ocsp_responder
> +
> +test_expect_success 'setup repository' '
> + test_commit one &&
> + git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
> + git push "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" HEAD:refs/heads/main
> +'
> +
> +# lib-httpd.sh exports GIT_SSL_NO_VERIFY, which would keep us from ever
> +# looking at the certificate. Trust our own CA instead.
> +with_ssl_verification () {
> + (
> + sane_unset GIT_SSL_NO_VERIFY &&
> + GIT_SSL_CAINFO="$HTTPD_ROOT_PATH/ca.pem" "$@"
According to our CodingGuidelines, a temporary variable assignment
like this should not be used for shell functions for portability
reasons. In most test cases this is fine, becase "$@" is a git
command, but ...
> + )
> +}
> +
> +test_expect_success SSL_VERIFYSTATUS 'certificate verification works against test CA' '
> + with_ssl_verification git ls-remote "$HTTPD_URL/smart/repo.git" >actual &&
> + test_line_count -gt 0 actual
> +'
> +
> +test_expect_success SSL_VERIFYSTATUS 'fetch succeeds with stapled "good" OCSP response' '
> + with_ssl_verification git -c http.sslVerifyStatus=true \
> + ls-remote "$HTTPD_URL/smart/repo.git" >actual &&
> + test_line_count -gt 0 actual
> +'
> +
> +test_expect_success SSL_VERIFYSTATUS 'revoked certificate is rejected' '
> + revoke_httpd_cert &&
> + with_ssl_verification test_must_fail git -c http.sslVerifyStatus=true \
> + ls-remote "$HTTPD_URL/smart/repo.git" 2>err &&
> + test_grep -i -e "ocsp" -e "revocation" -e "revoked" -e "certificate status" err
> +'
... in this case "$@" is the test_must_fail shell function.
Please set and then export that variable instead; it's already in a
subshell because of the sane_unset anyway.
> +# Depends on the certificate revoked by the preceding test.
> +test_expect_success SSL_VERIFYSTATUS 'revoked certificate is accepted without http.sslVerifyStatus' '
> + with_ssl_verification git ls-remote "$HTTPD_URL/smart/repo.git" >actual &&
> + test_line_count -gt 0 actual
> +'
So this test case fails for me with the following trace output:
expecting success of 5585.5 'revoked certificate is accepted without http.sslVerifyStatus':
with_ssl_verification git ls-remote "$HTTPD_URL/smart/repo.git" >actual &&
test_line_count -gt 0 actual
+ with_ssl_verification git ls-remote https://127.0.0.1:5585/smart/repo.git
+ sane_unset GIT_SSL_NO_VERIFY
+ unset GIT_SSL_NO_VERIFY
+ return 0
+ GIT_SSL_CAINFO=/home/szeder/src/git/t/trash directory.t5585-http-ssl-ocsp/httpd/ca.pem git ls-remote https://127.0.0.1:5585/smart/repo.git
fatal: unable to access 'https://127.0.0.1:5585/smart/repo.git/': server certificate verification failed. CAfile: /home/szeder/src/git/t/trash directory.t5585-http-ssl-ocsp/httpd/ca.pem CRLfile: none
error: last command exited with $?=128
not ok 5 - revoked certificate is accepted without http.sslVerifyStatus
#
# with_ssl_verification git ls-remote "$HTTPD_URL/smart/repo.git" >actual &&
# test_line_count -gt 0 actual
#
libcurl is 7.81.0, apache is 2.4.52 (whatever is shipped in this
slowly aging LTS...)
next prev parent reply other threads:[~2026-09-23 21:07 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 17:02 [PATCH] http: add http.sslVerifyStatus to check stapled OCSP responses graysongordon-gl
2026-08-11 19:28 ` Junio C Hamano
2026-08-11 20:44 ` [PATCH v2] " graysongordon-gl
2026-08-12 6:25 ` Patrick Steinhardt
2026-08-12 15:53 ` Grayson Gordon
2026-08-12 14:17 ` Junio C Hamano
2026-08-12 18:25 ` [PATCH v3] " graysongordon-gl
2026-08-12 21:34 ` Junio C Hamano
2026-08-13 16:06 ` Junio C Hamano
2026-08-17 18:52 ` [PATCH v4] " graysongordon-gl
2026-08-17 19:19 ` Junio C Hamano
2026-08-18 7:50 ` Patrick Steinhardt
2026-08-18 14:51 ` Grayson Gordon
2026-08-19 8:14 ` Patrick Steinhardt
2026-08-18 16:40 ` Junio C Hamano
2026-08-18 19:37 ` [PATCH v5] " graysongordon-gl
2026-08-18 20:12 ` Junio C Hamano
2026-08-18 21:22 ` Grayson Gordon
2026-08-18 21:48 ` [PATCH v6] " graysongordon-gl
2026-08-26 22:01 ` Junio C Hamano
2026-08-28 13:51 ` Grayson Gordon
2026-08-28 17:20 ` Junio C Hamano
2026-08-31 6:56 ` Patrick Steinhardt
2026-08-31 14:16 ` Junio C Hamano
2026-08-31 14:24 ` Patrick Steinhardt
2026-08-31 14:31 ` Junio C Hamano
2026-09-08 12:55 ` Grayson Gordon
2026-09-15 16:23 ` [PATCH v7] " graysongordon-gl
2026-09-16 19:29 ` Junio C Hamano
2026-09-23 12:42 ` Patrick Steinhardt
2026-09-23 21:43 ` Junio C Hamano
2026-09-23 21:07 ` SZEDER Gábor [this message]
2026-09-23 21:47 ` Junio C Hamano
2026-09-24 7:41 ` SZEDER Gábor
2026-09-24 7:59 ` Patrick Steinhardt
2026-09-25 9:28 ` SZEDER Gábor
2026-09-25 16:13 ` Junio C Hamano
2026-09-24 16:22 ` Junio C Hamano
2026-10-07 18:18 ` Junio C Hamano
2026-10-08 4:57 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=arQ/nOH+o3XwQFD/@szeder.dev \
--to=szeder.dev@gmail.com \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=graysongordon1@gmail.com \
--cc=peff@peff.net \
--cc=ps@pks.im \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox