01

Installation

Three supported channels. The Go install is the simplest; the Nix derivation is what your coworkers will thank you for picking.

Go, system-wide

$ go install github.com/flaticols/gitmd/cmd/gitmd@latest

Go tool, project-pinned

# Go 1.24+, version recorded in go.mod
$ go get -tool github.com/flaticols/gitmd/cmd/gitmd@latest
$ go tool gitmd show

Nix, macOS

$ nix-env -if https://github.com/flaticols/gitmd/raw/latest/nix/gitmd.nix

Platforms

The release pipeline currently ships aarch64-darwin and x86_64-darwin. Linux users build from source.

02

Quickstart

Every gitmd verb takes an optional <ref> — anything git rev-parse accepts. Omit it and you operate on HEAD, which is what you want most of the time.

# attach reasoning + ticket to the commit you just made
$ gitmd add --reason "required for audit" --ticket JIRA-1234

# replace, don't append
$ gitmd set --ticket JIRA-2

# pretty-print, or hand to jq
$ gitmd show
$ gitmd show HEAD~3 --json

# reach back two commits, attach an arbitrary trailer
$ gitmd add HEAD~2 --trailer "Reviewed-by=Alice <a@x>"

Real show output

From the very commit that introduced this page. Pretty form for humans, --json for jq and friends.

$ gitmd show
commit  33d2dff8 — docs: add retro-styled single-page HTML reference manual
author  Denis Panfilov <gh@flaticols.dev>  2026-04-28T20:21:52+02:00

  Reason    single-page reference manual for the project; satisfies the docs/ workflow added on origin
  Assisted  Claude Code (Opus 4.7)
$ gitmd show --json
{
  "commit": "33d2dff8be6ea9b3a534d64cc3e13773cf1cc439",
  "subject": "docs: add retro-styled single-page HTML reference manual",
  "author": {
    "name":  "Denis Panfilov",
    "email": "gh@flaticols.dev",
    "date":  "2026-04-28T20:21:52+02:00"
  },
  "trailers": [
    { "key": "Reason",   "value": "single-page reference manual for the project; satisfies the docs/ workflow added on origin" },
    { "key": "Assisted", "value": "Claude Code (Opus 4.7)" }
  ]
}

The why belongs on the commit, not in a wiki that will rot.

03

Commands

Five verbs. Three of them rewrite history and refuse to run on a dirty tree; the other two are pure reads.

command behaviour
add [<ref>] Append trailers. Idempotent — skips identical neighbours.
set [<ref>] Replace trailers that share the same key.
del [<ref>] Remove trailers by key.
show [<ref>] Pretty-print trailers; --json for machines.
version Print gitmd + detected git version.
04

Trailer keys

Three predefined shortcuts cover the cases worth standardising. Anything else lives behind --trailer KEY=VALUE, which is repeatable.

  • flag · --reason

    Reason

    The motivation. Why this diff exists — the constraint, the bug, the user request. One sentence is enough.

  • flag · --ticket

    Ticket

    An issue or PR identifier. JIRA-1234, gh-42, anything machine-readable.

  • flag · --assisted

    Assisted

    For AI-assisted commits. The model name and version: Claude Code 4.7.

  • flag · --trailer

    Idea / arbitrary

    Design notes, follow-ups, paths-not-taken. Or any custom key — Reviewed-by, Tested-by, etc.

05

How it works

For HEAD, gitmd shells out to git commit --amend. For any other reachable commit it runs an interactive rebase with itself registered as GIT_SEQUENCE_EDITOR — the editor inserts a surgical exec git commit --amend -F <newmsg> after the target's pick line.

Trailer composition is delegated to git interpret-trailers, so gitmd inherits git's exact semantics — folded values, the --- divider, and the twenty-five percent trailer-line tolerance.

06

Safety

History rewriting should never surprise you. gitmd is conservative on purpose.

Refuses dirty trees

If git status has anything pending, gitmd bails out before touching history. Stash or commit first.

Won't amend non-HEAD merges

Rewriting a merge commit's message via interactive rebase is a footgun. gitmd refuses; do it by hand if you must.

Never force-pushes

If the rewritten commit was already published, you run git push --force-with-lease yourself — gitmd does not.