Skip to content
LatchkeyLatchkey home

git log --pretty=format: Custom Output in CI

git log --pretty=format:"%H %an %s" prints only the fields you name using placeholders, the right way to get machine-readable commit data instead of parsing the default layout.

Pipelines that build changelogs or extract commit metadata should never parse the human git log output. --pretty=format with explicit placeholders gives a stable, scriptable result; -z and %x00 make it safe to split.

What it does

git log --pretty=format:<string> renders each commit using placeholders: %H full SHA, %h short SHA, %an/%ae author name/email, %ad author date, %s subject, %b body, %d ref names. %x00 inserts a NUL for unambiguous field splitting. Combined with --no-merges, range args, and -n it produces exactly the slice a job needs.

Common usage

Terminal
git log --pretty=format:'%h %an %s' -n 20
# changelog since the last tag
git log --pretty=format:'- %s (%an)' v1.4.0..HEAD --no-merges
# NUL-separated fields for safe parsing
git log --pretty=format:'%H%x00%an%x00%s' -z
# ISO dates
git log --pretty=format:'%h %ad %s' --date=short

Options

Placeholder / flagWhat it does
%H / %hFull / abbreviated commit SHA
%an / %aeAuthor name / email
%ad / %cdAuthor / committer date (see --date)
%s / %bSubject / body of the message
%x00Insert a NUL byte as a field separator
--date=<fmt>Format dates (short, iso, unix, relative)

In CI

git log starts a pager when attached to a terminal; in CI it is not, so it runs straight through, but add --no-pager (or set GIT_PAGER=cat) if a wrapper allocates a TTY and the job hangs. Use %x00 with -z and split on NUL so commit subjects containing spaces or quotes do not corrupt your parser. A range like v1.4.0..HEAD needs that tag present (not shallow).

Common errors in CI

"fatal: your current branch 'main' does not have any commits yet" means an empty repo. "fatal: ambiguous argument 'v1.4.0..HEAD'" means the tag is missing (shallow clone, tags not fetched). A hang with no output is almost always a pager on an allocated TTY; use --no-pager.

Using this in CI

CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.

.github/workflows/ci.yml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0   # history, tags, and git describe all need this

- run: |
    git rev-parse --is-shallow-repository   # expect false
    git rev-parse --abbrev-ref HEAD          # prints HEAD when detached

Frequently asked questions

git log --pretty=format: Custom Output in CI?
Pipelines that build changelogs or extract commit metadata should never parse the human git log output. --pretty=format with explicit placeholders gives a stable, scriptable result; -z and %x00 make it safe to split.
What it does?
git log --pretty=format:<string> renders each commit using placeholders: %H full SHA, %h short SHA, %an/%ae author name/email, %ad author date, %s subject, %b body, %d ref names. %x00 inserts a NUL for unambiguous field splitting. Combined with --no-merges, range args, and -n it produces exactly the slice a job needs.
In CI?
git log starts a pager when attached to a terminal; in CI it is not, so it runs straight through, but add --no-pager (or set GIT_PAGER=cat) if a wrapper allocates a TTY and the job hangs. Use %x00 with -z and split on NUL so commit subjects containing spaces or quotes do not corrupt your parser.
Common errors in CI?
"fatal: your current branch 'main' does not have any commits yet" means an empty repo. "fatal: ambiguous argument 'v1.4.0..HEAD'" means the tag is missing (shallow clone, tags not fetched). A hang with no output is almost always a pager on an allocated TTY; use --no-pager.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card