Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 77 additions & 2 deletions notes/commit-signing.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ on 2026-10-19.

## The routine

On the machine with your key, for a branch a session prepared:
On the machine with your key, for a branch a session prepared before review
started, or after Joshua asked for a rebase:

```sh
git fetch upstream main # JoshuaJewell/MetaManifold-WebUI
Expand All @@ -29,6 +30,53 @@ git log --format='%h %G? %s' upstream/main..HEAD # see the table below
git push --force-with-lease origin <branch> # before review, or after a requested rebase
```

The `--exec` line replays every commit after `upstream/main` onto its tip, so on
a branch that started from an older `main` it is itself a rebase, whether or not
the line before it ran.

### A PR already under review

Once review has started, re-sign only the commits added since the head Joshua
reviewed, and push them as a fast-forward; the reviewed commits keep their
hashes and signatures:

```sh
git fetch origin <prepared-branch> <pr-branch> # this fork
git switch -c <local> origin/<prepared-branch>
git merge-base --is-ancestor <reviewed-head> HEAD &&
git rebase --exec 'git commit --amend --no-edit -S' <reviewed-head>
git log --format='%h %G? %s' <reviewed-head>..HEAD # see the table below
git push origin <local>:<pr-branch> # fast-forward: no --force
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

`<reviewed-head>` is the PR's head commit when the review was given, and the
prepared branch must contain it. The `merge-base` check stops the re-sign when
it does not. Without that check, `git rebase <reviewed-head>` would replay the
branch onto the reviewed head, along with any upstream commits it carries, and
the push would then go through as a fast-forward. On `wip/pr62-theta`, for
example, it would replay Joshua's `78ffc2f` re-signed as yours, together with
copies of the PR's own commits. When the check stops it, nothing is rewritten,
and pushing the untouched branch is refused as a non fast-forward.

### Squash-merging the fork PR instead

Squash-merging a fork PR into `upstream/<topic>` on GitHub also works: GitHub
signs the squash commit (Verified, with its own key) and the upstream PR moves
forward by that one commit. Three things change:

- The prepared commits become one, so their separate messages are lost.
- The squash commit's message defaults to the fork PR's title and description,
fork-internal notes and `(#NNN)` fork references included, and it lands on
Joshua's `main` unchanged. Replace it in the merge dialog with a message that
stands on its own upstream (upstream CONTRIBUTING item 8).
- The signature is GitHub's key, not yours. It shows Verified, but upstream
CONTRIBUTING item 3 asks for a key registered to your account, so this path
has not been cleared with Joshua. (This fork's own CONTRIBUTING numbers its
items differently.)

This happened with #192: its squash commit `e28e832` on `upstream/glmgampoi-r`
carries #192's whole description as its message.

What `%G?` prints, and what to do:

| status | meaning | action |
Expand All @@ -50,4 +98,31 @@ GitHub's Verified badge is what upstream checks.

## Branches known to need re-signing

- `wip/pr62-theta` (3 unsigned commits, 2026-10-19), if it becomes a PR.
- `refs/pull/192/head` (`10e099b`): #192's three unsigned commits on PR 62's
reviewed head `efe1df1`. They are to replace the squash commit `e28e832` on
`upstream/glmgampoi-r` (owner's call, 2026-10-20); the tree is identical.
GitHub keeps a merged PR's head ref after its branch is deleted, so:

```sh
git fetch origin pull/192/head:pr62-next upstream/glmgampoi-r
git switch pr62-next
git merge-base --is-ancestor efe1df1 HEAD &&
git rebase --exec 'git commit --amend --no-edit -S' efe1df1
git log --format='%h %G? %s' efe1df1..HEAD # see the table above
git diff --stat origin/upstream/glmgampoi-r HEAD # expect no output
git push --force-with-lease=upstream/glmgampoi-r:e28e832fd52466f5192406025fe6b16d9fd99ae1 \
origin pr62-next:upstream/glmgampoi-r
```

The lease names `e28e832`, so the push is refused if anything else has
landed there since.

## Superseded branches

Kept for the record. Do not re-sign or push them.

- `wip/pr62-theta` is superseded: #192 carried its theta commit on PR 62's
reviewed head `efe1df1`, and was squash-merged as `e28e832`. Its other two
commits are PR 62's, rebased onto upstream `78ffc2f` after review had
started, so it should not be pushed to `upstream/glmgampoi-r`. Kept, not
deleted.
Loading