Writing release announcements
A maintainer runs shortlog over the range between the previous and new tags. This produces a by-author list of changes to paste into the announcement.
Git · Command
git shortlog condenses commit history into a list grouped by contributor, with each person's commit subjects under their name. It is meant for release notes and contributor statistics.
Last updated
git shortlog walks history like git log and accepts the same options for choosing commits, such as revision ranges, paths, dates and --no-merges. Instead of printing every commit in full, it puts commits into buckets and prints each bucket's header followed by its commit subjects. By default the buckets are authors, sorted alphabetically. You can bucket by committer, by a trailer such as Reviewed-by, or by any git log format string. You can also replace the subjects with counts. It can read git log output from a pipe instead of a repository, and it applies .mailmap so that one person's different identities are merged into one.
git shortlog [<options>] [<revision-range>] [[--] <path>…]
git log --pretty=short | git shortlog [<options>]| Name | Type | Description |
|---|---|---|
-n, --numbered | flag | Sorts groups by how many commits they have instead of alphabetically. |
-s, --summary | flag | Prints only a commit count for each group and leaves out the subjects. |
-e, --email | flag | Adds each author's email address to the output. |
--format[=<format>] | string | Describes each commit with a git log pretty-format string instead of its subject. |
--date=<format> | string | Sets how dates are formatted. Most useful together with --group=format:<format>. |
--group=<type> | author | committer | trailer:<field> | format:<format> | Sets what commits are grouped by. The default is author, and you can pass it more than once. |
-c, --committer | flag | Short form of --group=committer. |
-w[<width>[,<indent1>[,<indent2>]]] | integers | Wraps and indents the output lines. A width of 0 indents the lines without wrapping them. |
<revision-range> | revision range | Limits the summary to commits in this range, for example origin..HEAD. Defaults to HEAD. |
[--] <path>... | paths | Limits the summary to commits that explain how the matching files came to be. |
Text on standard output: one header per group (with a commit count) followed by indented commit descriptions, or only counts and names when -s is used.
git shortlog reads from stdin instead of the repository and may print nothing. Pass an explicit revision such as HEAD.#!/usr/bin/env bash
set -euo pipefail
# Ranked contributor counts with emails for the whole history
git shortlog -sne HEAD
# Release notes: commit subjects per author between two tags, skipping merges
git shortlog --no-merges v1.0..v2.0
# Who has been reviewing? Count Reviewed-by trailers
git shortlog -ns --group=trailer:reviewed-by HEAD
# Credit authors and co-authors together
git shortlog -ns --group=author --group=trailer:co-authored-by HEAD
# Commits per year, grouped by a date format
git shortlog -s --date=format:%Y --group=format:%ad HEAD
# Summarize piped log output from a topic branch
git log main..feature | git shortlogEach command passes an explicit revision (or reads from a pipe) so it behaves the same in scripts and in a terminal, and together they show counting, release notes, trailer grouping, multi-grouping and date grouping.
A maintainer runs shortlog over the range between the previous and new tags. This produces a by-author list of changes to paste into the announcement.
A team that adds Reviewed-by trailers groups history by that trailer to see who does the most reviewing.
Before merging, a developer pipes the log of commits not yet on main into shortlog to see a summary of the branch's changes and who wrote them.
Grouping by a formatted author date gives a count of commits per year or per month for project health reports.
Run git shortlog -sne HEAD. -s replaces the commit subjects with a count, -n sorts by that count instead of by name, and -e adds email addresses. Including HEAD explicitly avoids the stdin behavior when running in a script.
Follow-up: The same person appears twice under different emails. How do you merge them? Add a .mailmap file that maps the old identities to one canonical name and email; shortlog applies the mailmap when it groups commits.
git shortlog print nothing in a CI pipeline when it works fine in your terminal?When no revisions are given and stdin is not a terminal, or there is no current branch (as with a detached HEAD in many CI checkouts), shortlog summarizes log text read from stdin instead of the repository. In CI stdin is usually empty or redirected, so there is nothing to summarize. Passing a revision such as HEAD or a tag range fixes it.
Follow-up: How can you deliberately use the stdin mode? Pipe git log output into it, for example git log main..feature | git shortlog; outside a repository it then looks for .mailmap in the current directory.
Pass --group more than once, for example --group=author --group=trailer:co-authored-by. Each commit then counts under its author and under each distinct Co-authored-by value. The trailer name is matched without regard to case, and trailer values that look like 'Name <email>' are parsed as identities and passed through the mailmap.
Follow-up: Why can the counts add up to more than the total number of commits? A single commit is counted once in every group it matches, such as its author and each of its co-authors, so totals across groups overlap.
git loggit blamegitmailmapgit interpret-trailersgitrevisionsgit describe