How can a team enforce an Assisted-by trailer on commits?
Check for the trailer in two places: a commit-msg hook that stops the commit on the developer's machine, and a CI job that checks every commit in a pull request and blocks the merge. The hook is a convenience that can be skipped; the CI check is the rule. Neither can tell whether the line is true.
Cite
CodeLifter Forum, "How can a team enforce an Assisted-by trailer on commits?", https://forum.codelifter.com/posts/how-can-a-team-enforce-an-assisted-by-trailer-on-commits/, accessed 2026-10-16.- CodeLifter editorsStaffStaff, CodeLifter ·
Decide what the rule actually says
A check can only test for text, so write the rule first. Three decisions matter:
- Which key. The Linux kernel asks AI-assisted contributions to include an Assisted-by tag. Mesa uses Assisted-by, keeps Generated-by for commits where almost all the code was generated, and reserves Co-authored-by for human co-authors. The Apache Software Foundation recommends a
Generated-by:token. Pick one key and write it down. - Every commit or only assisted ones. A check cannot detect assisted commits that leave the trailer out. If you want enforcement, the workable form is to require the trailer on every commit, with an explicit value such as
Assisted-by: nonewhen no tool helped. Thatnonevalue is a team convention, not something the kernel or Mesa specify; projects that follow those documents only add the trailer when a tool was used. - What the value must contain. The kernel's guidance and LLVM's policy both keep the human contributor responsible for the change, and LLVM gives an Assisted-by line as its example of labelling tool-generated content. A free-text value naming the tool is enough for most teams; a team that wants to count usage can require a fixed list of tool names.
The policy tracker at CodeLifter's AI-code policy tracker lists which projects ask for which label, if you want to align with an upstream you contribute to.
How Git reads a trailer
The git-interpret-trailers manual defines a trailer as a key-value pair with a colon as the separator, in a block at the end of the message that must be preceded by a blank line. Its
--parseoption prints only the trailers it finds. That is the part to check, rather than searching the whole message, because a body line that happens to start withAssisted-by:in the middle of a paragraph is not a trailer.A valid message looks like this:
feat: add keyboard support to the slideshow Arrow keys move between slides; focus stays on the controls. Assisted-by: code assistant (tests written by hand)To add the line to a message file from a script, the same manual documents
git interpret-trailers --trailer "Assisted-by: none" --in-place msg.txt.Step 1: a commit-msg hook on each machine
The githooks documentation says the commit-msg hook receives one parameter, the file holding the proposed message, and that a non-zero exit aborts the commit. Save this as
.githooks/commit-msgin the repository and make it executable withchmod +x .githooks/commit-msg:#!/bin/sh # Reject the commit if the message has no Assisted-by trailer. if ! git interpret-trailers --parse "$1" | grep -qi '^Assisted-by: '; then echo "commit-msg: add an Assisted-by: trailer (Assisted-by: none if no tool helped)" >&2 exit 1 fiEach developer then runs
git config core.hooksPath .githooksonce in their clone. By default hooks live in$GIT_DIR/hooks, andcore.hooksPathis the documented way to point Git somewhere else, which lets you keep the hook under version control.Two limits, both in the same documentation: the hook only runs where someone has set it up, and commit-msg can be bypassed with
--no-verify. Commits created through a hosting service's API do not pass through anyone's local Git, so local hooks never see them, which matters if an agent commits through an MCP server; see who is the author of a commit made through an MCP server.Step 2: a CI check on every pull request
This is the step that enforces the rule. Save the script as
scripts/check-trailers.sh:#!/bin/sh # usage: scripts/check-trailers.sh <base> <head> fail=0 for c in $(git rev-list --no-merges "$1..$2"); do if ! git log -1 --format=%B "$c" | git interpret-trailers --parse | grep -qi '^Assisted-by: '; then echo "missing Assisted-by trailer: $(git log -1 --format='%h %s' "$c")" fail=1 fi done exit $failThen:
- In your CI configuration, make sure the checkout includes the history between the target branch and the pull request. A shallow checkout of one commit does not contain the range the script walks; look for a fetch depth setting.
- Run
sh scripts/check-trailers.sh origin/main HEAD, replacingmainwith your target branch. - Make the merge depend on that job passing. The setting has a different name on each hosting service, so look for required or blocking status checks in your repository's branch settings.
- If your repository squash-merges, the commit that lands is a new one with its own message. Check that message too, or the trailer can be lost at the last step.
Step 3: a server hook if you host Git yourself
On a self-hosted server you can run the same loop in a pre-receive hook. The githooks documentation says pre-receive reads one line per ref on standard input, in the form
<old-oid> <new-oid> <ref-name>, and that a non-zero exit means none of the refs are updated. Feed each old and new pair to the loop above. For a new branch the old value is all zeroes, so compare against your main branch instead.What enforcement cannot do
Check Stops a missing trailer Can be skipped Proves the trailer is true commit-msg hook On machines where it is set up Yes, with --no-verifyNo CI check on pull requests Yes, if the merge requires it By whoever can change the merge rules No pre-receive hook (self-hosted) Yes, at push time Only by the server admin No Every row ends in "No" for the same reason: a trailer is a statement a person makes. The value of the check is that the statement always exists and someone signed off on it. If a reviewer later doubts it, the conversation is about the code and the person, as covered in a detector flagged code written in 2019 as AI. For how projects word the disclosure itself, see disclosing AI help in commits.
- Which key. The Linux kernel asks AI-assisted contributions to include an Assisted-by tag. Mesa uses Assisted-by, keeps Generated-by for commits where almost all the code was generated, and reserves Co-authored-by for human co-authors. The Apache Software Foundation recommends a
Write something first.
Give people something to work with: at least 30 words on what happened and what you tried.
That is too long. Keep it under 6,000 characters.
Write the question as the title, 15 to 140 characters, no links.
Pick a category.
Add a name (2 to 40 characters, no links).
That email address does not look right.
That was quick. Read the thread, then try again.
The form expired. Reload the page and post again.
Something went wrong with the form. Reload and try again.
Please complete the check and post again.
Limit reached for now. Try again later.
This thread is closed to new replies.
This thread no longer accepts replies.
Something went wrong with the form. Reload and try again.
Post a reply or question first (name and email), then this browser can vote, edit and accept answers.
You cannot vote on your own post.
Only the author (within 30 days) or the forum team can do that.
That email belongs to a forum team account. Use your sign-in link instead.
New accounts are paused for the moment. Try again later.
That was already posted.