All of lore.kernel.org
 help / color / mirror / Atom feed
From: Souma <git@5ouma.me>
To: git@vger.kernel.org
Cc: gitster@pobox.com, ps@pks.im, Souma <git@5ouma.me>
Subject: [PATCH v3 0/2] history: support signing rewritten commits
Date: Sun, 13 Sep 2026 01:00:43 +0900	[thread overview]
Message-ID: <20260912160045.36064-1-git@5ouma.me> (raw)
In-Reply-To: <20260703145037.69832-1-git@5ouma.me>

The history commands create commits directly and via the replay
machinery, but currently have no way to honor `commit.gpgSign` or an
explicit signing request. This means users who require signed commits
lose that property when rewriting history.

Teach the replay API to accept a signing key, then expose the standard
`-S`/`--gpg-sign[=<key-id>]` and `--no-gpg-sign` interface across the
`git history drop`, `git history fixup`, `git history reword`, and `git
history split` subcommands. The selected policy applies to every new
commit, including both halves of a split and replayed descendants.

The implementation follows the precedence used by rebase, cherry-pick,
and revert: `commit.gpgSign` supplies the default, command-line options
override it, and the last command-line option wins.

The signature records the attestation of the current committer to the
rewritten commit while retaining the original author identity; it does
not claim authorship of commits written by somebody else.

Changes since v2:

 - Shorten the commit messages based on review feedback
 - Rename the history implementation commit from `builtin/history` to
   `history`
 - Fix the continuation-backslash formatting in `OPT_HISTORY_GPG_SIGN`

Souma (2):
  replay: allow callers to sign commits
  history: sign rewritten commits

 Documentation/git-history.adoc | 16 +++++--
 builtin/history.c              | 84 ++++++++++++++++++++++++++--------
 replay.c                       | 13 ++++--
 replay.h                       |  6 +++
 t/t3451-history-reword.sh      | 63 +++++++++++++++++++++++++
 t/t3452-history-split.sh       | 44 ++++++++++++++++++
 t/t3453-history-fixup.sh       | 39 ++++++++++++++++
 t/t3454-history-drop.sh        | 50 ++++++++++++++++++++
 8 files changed, 286 insertions(+), 29 deletions(-)

Range-diff against v2:
1:  3f4dc0b982 ! 1:  ca35b0acaa replay: allow callers to sign commits
    @@ Metadata
      ## Commit message ##
         replay: allow callers to sign commits

    -    The replay machinery creates commits directly through
    -    `commit_tree_extended()`, but callers cannot currently request
    -    signatures. Commands that replay rewritten history consequently cannot
    -    carry their signing policy through to descendant commits.
    -
    -    Add `sign_commit` to `replay_revisions_options` and thread it through
    -    commit creation. `NULL` preserves the existing unsigned behavior, an
    -    empty string selects the default signing key, and a non-empty string
    -    selects an explicit key. Existing callers zero-initialize the options
    -    structure, so their behavior is unchanged.
    +    Add a signing-key option to replay_revisions_options and pass it to
    +    commit_tree_extended() when creating replayed commits.

         Signed-off-by: Souma <git@5ouma.me>

    @@ replay.c: static struct commit *pick_regular_commit(struct repository *repo,
     +					  enum replay_empty_commit_action empty,
     +					  const char *sign_commit)
      {
    - 	struct commit *base, *replayed_base;
      	struct tree *pickme_tree, *base_tree, *replayed_base_tree;
    +
     @@ replay.c: static struct commit *pick_regular_commit(struct repository *repo,
      		}
      	}

     -	return create_commit(repo, result->tree, pickme, replayed_base, mode);
     +	return create_commit(repo, result->tree, pickme, replayed_base, mode,
    -+			     sign_commit);
    ++					    sign_commit);
      }

      void replay_result_release(struct replay_result *result)
     @@ replay.c: int replay_revisions(struct rev_info *revs,

    - 		last_commit = pick_regular_commit(revs->repo, commit, replayed_commits,
    - 						  mode == REPLAY_MODE_REVERT ? last_commit : onto,
    --						  &merge_opt, &result, mode, opts->empty);
    -+						  &merge_opt, &result, mode, opts->empty,
    -+						  opts->sign_commit);
    - 		if (!last_commit)
    - 			break;
    + 			last_commit = pick_regular_commit(revs->repo, commit, base,
    + 							  &merge_opt, &result,
    +-							  mode, opts->empty);
    ++							  mode, opts->empty,
    ++							  opts->sign_commit);
    + 		}

    + 		if (!last_commit)

      ## replay.h ##
     @@ replay.h: struct replay_revisions_options {
2:  0e63c0b66a ! 2:  f0a1a88411 builtin/history: sign rewritten commits
    @@ Metadata
     Author: Souma <git@5ouma.me>

      ## Commit message ##
    -    builtin/history: sign rewritten commits
    +    history: sign rewritten commits

    -    The history commands create replacement commits directly instead of
    -    using the sequencer or the commit porcelain. As a result, rewritten
    -    commits ignore `commit.gpgSign` and cannot be signed on demand.
    +    Add --gpg-sign/--no-gpg-sign support to git history and honor
    +    commit.gpgSign when creating replacement commits. Thread the selected
    +    signing key through direct rewrites and replayed descendants while
    +    preserving the original author identity.

    -    Read the signing configuration before parsing options so that it
    -    establishes the default and later `-S`/`--gpg-sign` or `--no-gpg-sign`
    -    options override it. Pass the selected key through direct rewrites and
    -    the replay machinery.
    -
    -    Sign every newly created commit, including both halves of a split and
    -    replayed descendants. Dropping the tip creates no replacement commit,
    -    so there is nothing to sign. As with `rebase --gpg-sign`, the signature
    -    records the attestation of the current committer to the rewritten
    -    commit while retaining the original author identity; it does not claim
    -    authorship of commits written by somebody else.
    -
    -    Document the behavior and add GPG-gated coverage for configuration,
    -    command-line overrides, last-option-wins precedence, replayed
    -    descendants, split commits, an explicit signing key, and the
    -    no-new-commit drop case.
    +    Cover configuration, command-line precedence, explicit keys, split commits,
    +    and replayed descendants with GPG-gated tests.

         Signed-off-by: Souma <git@5ouma.me>

    @@ builtin/history.c: enum commit_tree_flags {
     +	return git_default_config(var, value, ctx, NULL);
     +}
     +
    -+#define OPT_HISTORY_GPG_SIGN(v) {                 \
    -+	.type = OPTION_STRING,                    \
    -+	.short_name = 'S',                        \
    -+	.long_name = "gpg-sign",                  \
    -+	.value = (v),                             \
    -+	.argh = N_("key-id"),                     \
    ++#define OPT_HISTORY_GPG_SIGN(v) { \
    ++	.type = OPTION_STRING, \
    ++	.short_name = 'S', \
    ++	.long_name = "gpg-sign", \
    ++	.value = (v), \
    ++	.argh = N_("key-id"), \
     +	.help = N_("GPG-sign rewritten commits"), \
    -+	.flags = PARSE_OPT_OPTARG,                \
    -+	.defval = (intptr_t)"",                   \
    ++	.flags = PARSE_OPT_OPTARG, \
    ++	.defval = (intptr_t)"", \
     +}
     +
      static int commit_tree_ext(struct repository *repo,
--
2.55.0


  parent reply	other threads:[~2026-09-12 16:00 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-03 14:50 [PATCH 0/3] history: sign rewritten commits Souma
2026-07-03 14:50 ` [PATCH 1/3] builtin/history: " Souma
2026-07-16 10:18   ` Patrick Steinhardt
2026-07-03 14:50 ` [PATCH 2/3] doc: document history signing options Souma
2026-07-16 10:18   ` Patrick Steinhardt
2026-07-03 14:50 ` [PATCH 3/3] t345x: cover signed history rewrites Souma
2026-07-17 14:51 ` [PATCH v2 0/2] history: support signing rewritten commits Souma
2026-07-17 14:51 ` [PATCH v2 1/2] replay: allow callers to sign commits Souma
2026-09-11  7:57   ` Patrick Steinhardt
2026-07-17 14:51 ` [PATCH v2 2/2] builtin/history: sign rewritten commits Souma
2026-09-11  7:57   ` Patrick Steinhardt
2026-09-12 16:00 ` Souma [this message]
2026-09-12 16:00 ` [PATCH v3 1/2] replay: allow callers to sign commits Souma
2026-09-12 16:00 ` [PATCH v3 2/2] history: sign rewritten commits Souma

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=20260912160045.36064-1-git@5ouma.me \
    --to=git@5ouma.me \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.