Preserving co-authors when squashing Jump to heading

A commit has exactly one author field. When a branch with commits from three people is squashed into one commit, two of them vanish from the author field — and from git shortlog, contribution graphs, and the “who wrote this” answer that git blame gives. For pairing sessions, handed-over pull requests and reviewers who pushed fixes, that is a real loss: credit, but also the ability to ask the right person about the code later. The Co-authored-by trailer solves it. Forges display co-authors on the commit, count the contribution, and tools can read the trailer. The difficulty is remembering to add it at squash time, which is why it should be automatic. This page shows how, within squash and fixup strategies.

When to use this approach Jump to heading

  • Pull requests are squash-merged, and more than one person sometimes commits to a branch.
  • Your team pairs or mobs, so commits are written together even when one person types.
  • Contribution metrics or open-source credit matter to the people involved.
  • You squash locally before pushing, or squash on the forge with the merge button — both are covered.

Step 1 — Understand the trailer format Jump to heading

A trailer is a Key: value line in the last paragraph of a commit message. The co-author trailer uses the same name-and-email format as the author field. The email must match an address associated with the person’s forge account for the forge to link it.

Add per-account export scheduling

Co-authored-by: Priya Raman 
Co-authored-by: Tom Okafor 
# Verification: Git parses it as a trailer
git log -1 --format='%(trailers:key=Co-authored-by)'
Squashing with and without co-author trailersWithout trailers, a squash keeps only the person who merged as author, and everyone else disappears from shortlog, blame and contribution graphs. With trailers, the forge shows every contributor on the commit and tools can count them.No trailersCo-authored-by trailersauthor fieldone personone personforge showsone avatarall contributorsshortlog / metricsone person creditedparseable for allwho to ask laterone nameevery namethe author field cannot hold more than one person — the trailer is the only fix

Step 2 — Collect co-authors from the branch automatically Jump to heading

Every author and committer on the branch, other than the person squashing, is a candidate co-author. Collect them from the commits about to be squashed, deduplicate by email, and drop bots.

#!/bin/sh
# coauthors.sh <base> [<head>] — print Co-authored-by trailers for a range
set -eu
base=$1 head=${2:-HEAD}
me=$(git config user.email)
git log --format='%an <%ae>%n%cn <%ce>' "$base..$head" |
  grep -v -e "<$me>" -e '[email protected]' -e '\[bot\]' |
  sort -u | sed 's/^/Co-authored-by: /'

Including committers as well as authors catches people who applied, rebased or amended others’ work, which matters in workflows where a maintainer finishes a contributor’s branch.

# Verification: list who would be credited for this branch
./coauthors.sh main feature/export-scheduling

Step 3 — Add them when squashing locally Jump to heading

When you squash locally — with a soft reset, merge --squash or an interactive rebase — append the trailers to the final message.

base=$(git merge-base main HEAD)
trailers=$(./coauthors.sh "$base")
git reset --soft "$base"
git commit -m "feat(export): schedule CSV exports per account" -m "$trailers"

Or with --trailer, which formats and deduplicates for you:

./coauthors.sh "$base" | while IFS= read -r line; do
  git commit --amend --no-edit --trailer "$line"
done
Keeping credit through a local squashBefore squashing, the script reads every author and committer on the branch. The branch is reset softly to its base, and the single new commit is created with the collected Co-authored-by trailers, so the forge credits everyone after the push.Read rangeauthors + committersFilterdrop self, botsreset --softto the baseCommitwith trailerscollect before you squash — afterwards the information is gone from the branch

Step 4 — Make the forge’s squash button include them Jump to heading

Forges add co-author trailers automatically for commits authored by other people on the branch when you squash through the interface, but only if the commit authors are recognised accounts and the default message includes the commit list or co-author section. Check what your forge produces on a test pull request before relying on it.

# After a squash merge, verify the trailers landed on main
git fetch origin
git log -1 --format='%an%n%(trailers:key=Co-authored-by)' origin/main

If the forge drops them — for instance when the default message is set to the pull request description only — add them to the description before merging, or use a merge-time script like the one in writing a good squash commit message.

Step 5 — Credit pairing partners at commit time Jump to heading

When two people pair at one keyboard, the commits on the branch have one author before any squash happens. Add the partner as a co-author on each commit, so the squash script has something to collect. A commit template makes that low effort.

# .gitmessage — prefilled when the pair starts, removed when they stop
# Co-authored-by: Priya Raman <[email protected]>
git config commit.template .gitmessage
Credit through a pairing session and a squashDuring pairing, each commit carries the partner's trailer from the template. At merge time, the squash collects authors and existing co-author trailers from the branch, deduplicates them, and writes them into the final commit, which the forge displays with both names.pairbranch commitssquashforgecommits + trailer from templatecollect authors + trailersdeduplicateone commit, both creditedalso collect existing Co-authored-by trailers, not just author fields

To include existing trailers in the collection, extend the script: git log --format='%(trailers:key=Co-authored-by,valueonly)' "$base..$head" prints them, ready to merge into the list.

Validation checklist Jump to heading

Frequently Asked Questions Jump to heading

Does the email have to match the person’s forge account? Jump to heading

For the forge to link the trailer to an account and show their avatar, yes — it must be an email on their account, including the forge’s private noreply address if they use one. The trailer is still recorded in history either way.

Is a co-author the same as a reviewer? Jump to heading

No. Use co-author for people who wrote code in the change. Reviewers can be recorded with a Reviewed-by trailer if your team values that, but forges do not treat it as authorship.

Can I add co-authors to a commit that is already on main? Jump to heading

Not without rewriting main, which is not worth it. Record the credit in the pull request instead, and fix the process so the next squash includes them.