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://codelifter.com/forum/posts/how-can-a-team-enforce-an-assisted-by-trailer-on-commits/, accessed 2026-11-12.- 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 already has an account. Use your sign-in link instead.
New accounts are paused for the moment. Try again later.
That was already posted.
2 answers
- CodeLifter editorsStaffStaff, CodeLifter ·
How do you add a trailer from the command line without editing the message? Use
git commit --trailer. The git commit documentation describes--trailer <token>[(=|:)<value>]as a pair that should be applied as a trailer, and its own example adds two at once:git commit --trailer "Signed-off-by:C O Mitter <committer@example.com>" --trailer "Helped-by:C O Mitter <committer@example.com>". For this thread that becomes:git commit -m "Add keyboard support to slideshow" --trailer "Assisted-by: code assistant"Git places the line in the trailer block at the end of the message, after a blank line, which is what the hook and CI script in the opening post read with
git interpret-trailers --parse. The same page says thetrailer.*settings documented under git-interpret-trailers control whether a duplicated trailer is kept or omitted, so a team can decide what happens when a secondAssisted-byline is added. Avoid a shell alias that fills in a fixed value such asnone: it makes an untrue statement the easy path. Type the value each time, or tell the agent to add the line for the commits it makes, and let the CI check catch the ones where nobody did. - CodeLifter editorsStaffStaff, CodeLifter ·
What is the difference between Signed-off-by and Assisted-by? They answer different questions and carry different weight.
Signed-off-by:is a personal certification under the Developer Certificate of Origin. Clause (a) of DCO 1.1, as printed in the kernel's submitting patches guide, begins "The contribution was created in whole or in part by me"; clause (b) covers work based on earlier code under an open source licence, and clause (c) code passed on unmodified by someone who certified it. Only a person can make that statement, which is why the kernel says AI agents must not add the tag. The git commit documentation adds that the meaning of a signoff depends on the project, and that Git does not and will not have a setting to add--signoffby default.Assisted-by:is a disclosure: a note that a tool helped, naming it. The kernel's coding assistants page asks for it, and says basic development tools such as git, gcc, make and editors should not be listed. A commit to a project that uses both can carry both lines, one stating where the code came from and one stating which tool helped. Do not let either stand in for the other. A sign-off on code you have not read is the more serious problem of the two.