Edit and Inspect Commit Trailers with git interpret-trailers
git interpret-trailers adds, inspects and updates the Signed-off-by and Reviewed-by lines at the end of a commit message. Hand-editing them is fiddly and easy to get wrong; this keeps the message body and patch content recognisable while it works. The examples use Git 2.43.0, the installed version on this machine. Allow about fifteen minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need: Git and a text file containing a commit message.
- No sudo. The normal commands are unprivileged. This tool reads and writes the files you name, and elevated access would only make an accidental overwrite more damaging.
1. Check the installed command
Confirm the binary and version before relying on option details:
$ command -v git
/usr/bin/git
$ git --version
git version 2.43.0
The command reads files named on the command line, or standard input when no file is given. Without --in-place, it writes the transformed message to standard output, which is useful: you can review the result, or redirect it to a new file, before replacing an original.
2. Add a trailer without changing the source file
Create a small message in an editor, or use an existing message file. A trailer is a final line such as Reviewed-by: Name <[email protected]>, separated from the body by a blank line. Add one through standard input:
$ printf '%s\n' 'Subject' '' 'Body text.' | \
git interpret-trailers --trailer='Reviewed-by: Alice <[email protected]>'
Subject
Body text.
Reviewed-by: Alice <[email protected]>
Git adds a blank line when needed and formats the key and value with one colon and one space. The input was never stored anywhere, so there is nothing to undo. For a file, replace the pipeline with git interpret-trailers --trailer='...' message.txt.
3. Add several values and understand duplicates
Repeat --trailer when a key can occur more than once:
$ git interpret-trailers \
--trailer='Acked-by: Alice <[email protected]>' \
--trailer='Acked-by: Bob <[email protected]>' message.txt
By default, a new pair is appended only when the relevant neighbouring trailer does not already have the same key and value, so this does not create a second adjacent copy of an identical trailer:
$ printf '%s\n' 'Subject' '' 'Signed-off-by: Alice <[email protected]>' | \
git interpret-trailers \
--trailer='Signed-off-by: Alice <[email protected]>'
Subject
Signed-off-by: Alice <[email protected]>
The default is addIfDifferentNeighbor. Use --if-exists add when every requested occurrence must be kept, or --if-exists replace when the nearest existing trailer with that key should be replaced. Both change output policy, so inspect the result before writing it back.
4. Parse existing trailers only
Use --parse when another command needs the trailers already present. It outputs only input trailers, ignoring additions from configuration or the command line, and unfolds continuation lines:
$ printf '%s\n' 'Subject' '' 'Review: ready' ' for merge' | \
git interpret-trailers --parse
Review: ready for merge
Parsing is deliberately separate from editing. A common trap is using --trailer while trying to inspect a message: that can add configuration-driven or command-line trailers to the output. Use --parse for an input-only view, and check its output before feeding it to a script.
5. Configure a short alias for a repeated key
For a repository-specific workflow, define an alias in that repository. This changes Git configuration, so review the scope before running it; the command below uses --local and needs to run inside the intended repository:
$ git config --local trailer.sign.key 'Signed-off-by'
$ git config --local --get trailer.sign.key
Signed-off-by
Now sign is a prefix alias for the full key:
$ printf '%s\n' 'Subject' '' 'Body text.' | \
git interpret-trailers --trailer='sign: Alice <[email protected]>'
Subject
Body text.
Signed-off-by: Alice <[email protected]>
Undo this configuration change with:
$ git config --local --unset trailer.sign.key
If that reports the key is absent, the alias was already removed. Avoid --global unless you deliberately want the rule to affect every repository for this user.
6. Edit a file in place only after a review
--in-place writes back to each named file. It is the irreversible boundary in this guide: a failed or misunderstood transformation can replace the original contents. Preview the result and save a copy first:
$ cp --preserve=all message.txt message.txt.bak
$ git interpret-trailers \
--trailer='Reviewed-by: Alice <[email protected]>' \
message.txt > message.txt.new
$ diff -u message.txt message.txt.new
$ mv message.txt.new message.txt
Warning
The mv is the final, irreversible replacement, and should only run after the diff looks right. If the preview is wrong, remove the new file and keep the original. To recover after an unwanted replacement, restore the explicit backup with cp --preserve=all message.txt.bak message.txt. Do not delete the backup until the commit message has been checked.
7. Handle empty values and patch files carefully
--trim-empty removes trailers whose values contain only whitespace, including existing ones. This suits templates, but it deliberately deletes message lines from the output:
$ printf '%s\n' 'Subject' '' 'Cc: ' | \
git interpret-trailers --trim-empty
Subject
Git also understands the commit message and patch divider produced by git format-patch. By default, it leaves the divider and patch portion alone while editing the message trailers. Use --no-divider only when the input is definitely just a commit message and a line beginning with --- must not mark the patch boundary.
Trailer values may be folded across lines when continuation lines begin with whitespace. --parse and --unfold turn those values into one line, which is usually easier for scripts to consume. Do not assume every colon-separated line in a message is a trailer: Git only recognises trailer groups in the final, appropriately separated part of the input.
Done means
- Version checked. You checked that the installed command is Git 2.43.0, or reviewed the local version's help.
- Trailers added safely. You can add trailers through standard input or a file without accidentally changing the source.
- Parsing kept separate. You use
--parsewhen you need input trailers only. - Duplicates understood. You understand the default duplicate rule and can choose
addorreplacedeliberately. - Alias scoped. Any repository alias is scoped with
--localand can be removed with--unset. - Backup taken. You preview and back up before an in-place or empty-trailer cleanup operation.