Skip to content

amend that fixes a malformed trailer is refused as a duplicate Record-Id #638

Description

@MongLong0214

The commit-msg hook correctly warns that a wrapped Limit: line is not a trailer, then refuses the git commit --amend that fixes it. The only way out is --no-verify.

Sequence

Commit with a trailer block where two Limit: values are wrapped across two lines each, so they sit in their own paragraph above the real trailer block:

Limit: Fixtures intentionally copy the live authority tree; replacing that
structure with a wholly synthetic fixture is outside D0-013 exact ownership.
Limit: cleanupFixture intentionally suppresses cleanup errors so teardown
cannot obscure the test result; the known teardown-race tradeoff remains.

Warn: render witnesses depend on the live catalog and authority-tree fixture shape
Blast: local
...
Record-Id: r-d0013executionviewshardening

The hook lets the commit through with an accurate warning:

shape ok · references ok
commitlore: line 15 looks like a Limit trailer, but git did not parse it;
            the trailer block needs a blank line before it
commitlore: line 17 looks like a Limit trailer, but git did not parse it;
            the trailer block needs a blank line before it

git log --format='%(trailers:only=true,keyonly=true)' -1 confirms it: Warn Blast Undo Certainty Record-Id Follows Provenance X-Ticket. The two Limit values are absent from the record.

Amend the message to put both Limit: values on single lines inside the final block, keeping the same Record-Id:

$ git commit --amend -F fixed-message.txt
shape ok · references failed
21: duplicate-id Record-Id — got "r-d0013executionviewshardening",
    want "exactly one record per Record-Id"
commitlore: 1 violation (SPEC §6) — the message was not modified

Why this is wrong

--amend replaces the commit. After it, the old commit is unreachable from the branch and there is exactly one commit carrying that Record-Id. The duplicate the check reports does not exist in the resulting history — it exists only because the pre-amend commit was already recorded and the check does not know it is about to be replaced.

The two rules combine into a trap. The first rule tells you the message is malformed. The second rule blocks the correction, unless you either change the Record-Id — which is semantically wrong, since it is the same record — or bypass the hook. I used --no-verify, which is the outcome the hook exists to prevent.

Reproduction

  • macOS, commitlore --version0.8.2
  • Repository policy: {"mode": "auto", "unattended": true, "max_records_per_commit": 1, "require_verified_evidence": true}
  • Commit a message with a wrapped Limit: paragraph above the trailer block; observe the warning and that the trailer is absent from %(trailers)
  • git commit --amend with the same Record-Id and corrected formatting; observe duplicate-id
  • git commit --amend --no-verify succeeds and %(trailers:key=Limit) then returns both values

What would resolve it

The uniqueness check needs to exclude the commit being amended. GIT_COMMIT is not set for commit-msg on amend, but git rev-parse HEAD during an amend is the commit being replaced, so the check can compare against it and skip a match. Alternatively the check could scan only commits reachable after the operation rather than the recorded set.

A narrower fix that would also help: refuse the original commit instead of warning. If a malformed trailer is worth a warning, and correcting it is blocked, the warning has no action attached to it.

What I could not determine

Whether the same trap applies to rebase -i reword and to commit --amend on a commit whose record was staged through the capture pipeline rather than written by hand. I only exercised the hand-written trailer path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    release:0.9.0Must close before 0.9.0: an unaware user gets a wrong result, or the docs already promise it

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions