Skip to main content
ansicode

Git colour config — color.ui, slots, pager, --color=always

Git emits ANSI / VT escape codes for diff, status, log, branch, grep, and the interactive picker — each subcommand has its own switch, every output element has a named slot you can recolour, and the default less pager strips SGR unless you tell it not to. Seven copy-paste snippets below cover the full configuration map, from the global color.ui switch down to the canonical LESS=FRX pager flags and the git log --color=always | less -R pipe recipe.

Configuration snippets

color.ui — the global on/off switch (default since git 1.8.4)

Since git 1.8.4 (August 2013) the default for color.ui is auto — git emits SGR when stdout is a TTY and strips it when piped. Older builds defaulted to false; legacy .gitconfig files often pin false for no reason. The valid values are auto (TTY-only), always / true (always emit — useful when piping into a renderer like less -R), and never / false (never emit). color.ui is the only switch that affects all subcommands at once; per-command keys (color.diff etc.) override it.

.gitconfig / shell
# Inspect current value (auto = sane default).
git config --get color.ui

# The sane default — emit colour on TTY, strip on pipe:
git config --global color.ui auto

# Force colour through pipes (for piping into less -R, see snippet 6):
git config --global color.ui always

# Disable globally (e.g. dumb terminal, log scraping, or accessibility):
git config --global color.ui never
# or honour the universal env var (git respects NO_COLOR since 2.21):
NO_COLOR=1 git diff

color.diff / color.status / color.branch / color.grep / color.interactive — per-command override

Every subcommand that emits coloured output has its own color.<command> key that overrides color.ui for that command. Same values: auto, always / true, never / false. Use these when you want colour everywhere except one command (e.g. you pipe git status into a script but want git diff coloured), or when honouring a corporate .gitconfig that disables global colour but you want it back for diff.

.gitconfig / shell
# Per-command keys, all default to value of color.ui:
git config --global color.diff        auto
git config --global color.status      auto
git config --global color.branch      auto
git config --global color.grep        auto
git config --global color.interactive auto
git config --global color.decorate    auto     # git log --decorate
git config --global color.pager       true     # respect color when paged
git config --global color.advice      auto     # hint messages
git config --global color.push        auto     # since git 2.41
git config --global color.remote      auto     # since git 2.21

# Example: force colour for diff specifically, leave everything else auto:
git config --global color.diff always

color.<cmd>.<slot> — the named-slot palette system

Each subcommand has named "slots" — individual elements of its output you can recolour. The value syntax is <fg> [<bg>] [<attr>...], where colours are named (red / green / yellow / blue / magenta / cyan / white), numeric 256-palette (231), or 24-bit hex ("#ff8000", git 2.26+). Attributes: bold, dim, italic, underline, blink, reverse, strike. Prefix any of fg/bg/attr with no- to clear an inherited value. Slots not listed below fall back to git's built-in defaults.

.gitconfig / shell
# git diff slots — most commonly retuned for readability:
git config --global color.diff.meta       "yellow bold"
git config --global color.diff.frag       "magenta bold"
git config --global color.diff.func       "cyan"
git config --global color.diff.context    "white"
git config --global color.diff.old        "red bold"
git config --global color.diff.new        "green bold"
git config --global color.diff.whitespace "red reverse"
git config --global color.diff.commit     "yellow"

# git status slots:
git config --global color.status.header    "white"
git config --global color.status.added     "green"
git config --global color.status.updated   "green"
git config --global color.status.changed   "yellow"
git config --global color.status.untracked "red"
git config --global color.status.branch    "cyan bold"
git config --global color.status.nobranch  "red reverse"

# git branch slots:
git config --global color.branch.current  "green bold"
git config --global color.branch.local    "white"
git config --global color.branch.remote   "yellow"
git config --global color.branch.upstream "magenta"
git config --global color.branch.plain    "white"

# git grep slots (git 2.0+):
git config --global color.grep.filename     "magenta"
git config --global color.grep.linenumber   "yellow"
git config --global color.grep.match        "red bold"
git config --global color.grep.matchContext "white"
git config --global color.grep.separator    "white"

# Truecolor (git 2.26+, 2020):
git config --global color.diff.new "#3fb950 bold"
git config --global color.diff.old "#f85149 bold"

color.decorate.<slot> — git log --decorate ref colours

git log --decorate annotates each commit with the refs that point at it (branches, tags, HEAD, stash). Each ref kind has its own slot — useful when scanning a busy history and you want branches one colour, tags another, and HEAD popping out.

.gitconfig / shell
# git log --decorate slots:
git config --global color.decorate.branch       "green bold"
git config --global color.decorate.remoteBranch "red bold"
git config --global color.decorate.tag          "yellow bold"
git config --global color.decorate.stash        "magenta bold"
git config --global color.decorate.HEAD         "cyan bold"
git config --global color.decorate.grafted      "blue"

# Pair with a one-line graph to make refs even more legible:
git config --global alias.lg \
    "log --graph --oneline --decorate --all"
# Then: git lg

Canonical fully-coloured shell prompt config — bash + zsh

Git ships git-prompt.sh (in contrib/completion/) which exports __git_ps1 for bash / zsh. The coloured form (GIT_PS1_SHOWCOLORHINTS=1) renders branch / dirty / stash / upstream status in distinct colours. Below is the canonical wire-up — copy the block into ~/.bashrc or ~/.zshrc. The block does NOT use color.ui (it builds its own SGR via \[\e[...m\] brackets that bash counts as zero-width — wrong brackets break terminal line-editing).

.gitconfig / shell
# ~/.bashrc — fully-coloured git prompt
# (Debian / Ubuntu / Fedora ship git-prompt.sh under
# /usr/share/git-core/contrib/completion/git-prompt.sh;
# Homebrew ships it under
# /opt/homebrew/etc/bash_completion.d/git-prompt.sh.)

source /usr/share/git/completion/git-prompt.sh

# Colour hints: branch (green) / dirty (yellow) / staged (red).
export GIT_PS1_SHOWCOLORHINTS=1
# Show + for staged changes, * for unstaged.
export GIT_PS1_SHOWDIRTYSTATE=1
# Show $ if anything is stashed.
export GIT_PS1_SHOWSTASHSTATE=1
# Show % if there are untracked files.
export GIT_PS1_SHOWUNTRACKEDFILES=1
# Show ↑/↓ counts vs upstream.
export GIT_PS1_SHOWUPSTREAM="auto verbose"

# \[ ... \] tells bash these bytes are zero-width — required
# for correct line-edit wrap math. PROMPT_COMMAND lets
# __git_ps1 splice the git status into PS1 each prompt.
PROMPT_COMMAND='__git_ps1 "\[\e[36m\]\u\[\e[0m\]@\[\e[35m\]\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]" "\\\$ "'

# zsh equivalent (~/.zshrc) — drops \[ \] (zsh uses %{...%}):
# setopt PROMPT_SUBST
# source /usr/share/git/completion/git-prompt.sh
# PROMPT='%F{cyan}%n%f@%F{magenta}%m%f:%F{blue}%~%f$(__git_ps1 " (%s)") %# '

core.pager + LESS=FRX — why colours sometimes don't reach the pager

By default git pipes the output of git log, git diff, git show, git branch -a, etc. through a pager (less on most systems). The pipe is no longer a TTY — but git knows it pipes into its OWN pager and re-injects colour as if it were a TTY. The catch: less strips control characters by default and renders SGR escapes as ^[[31m literal noise. The fix is LESS=FRX-R keeps SGR alive, -F quits if output fits one screen (so short diffs don't trap you in less), and -X skips clearing the screen (so your scrollback retains the diff after you quit). git already sets LESS=FRX automatically when it invokes its default pager — but if you override core.pager or GIT_PAGER with a custom command you need to set LESS=FRX (or pass -R) yourself.

.gitconfig / shell
# Inspect current pager (most systems: 'less').
git config --get core.pager

# Sane explicit form — leaves colour intact, quits on short output:
git config --global core.pager "less -FRX"

# Or set LESS globally and leave core.pager unset:
export LESS=FRX                              # add to ~/.bashrc

# Custom pager — REMEMBER to set the flags yourself:
git config --global core.pager "less -+F -+X -R"   # don't auto-quit

# Disable the pager entirely (one-shot):
git --no-pager log

# Per-command pager override:
git config --global pager.diff "delta --side-by-side"   # ships colour itself
git config --global pager.log  "less -FRX +'/^commit'"  # jump to first commit
git config --global pager.branch false                  # no pager for branch -a

Forcing colour through a pipe — git log --color=always | less -R

Every git command accepts a per-invocation --color={auto,always,never} flag that overrides both color.ui and the per-command key. The canonical use is piping into a renderer that ISN'T git's own pager — less -R, bat, aha (HTML conversion), or tee while keeping colour. Without --color=always, git sees a non-TTY pipe and strips colour automatically. The pipe target needs to render SGR for the bytes to be useful — less -R, bat, aha, delta, ansi2html. Without it, you'll see ^[[31m noise.

.gitconfig / shell
# Pipe coloured log into less manually (with -R to render SGR):
git log --color=always --graph --oneline | less -R

# Same idea with diff — useful with side-by-side viewers:
git diff --color=always | bat --paging=always

# Convert coloured diff to HTML for a code review email / blog post:
git log --color=always --graph -p HEAD~5..HEAD | aha > review.html

# Pipe coloured log into tee, keep on screen AND save to file:
git log --color=always --oneline | tee --output-error=warn /tmp/log.ansi
# Strip later when archiving (see /strip):
sed -E 's/\x1b\[[0-9;]*m//g' /tmp/log.ansi > /tmp/log.txt

# fzf with coloured input — needs --ansi flag:
git log --color=always --oneline | fzf --ansi

Configuration-key matrix

Every git colour-related config key, the values it accepts, its default, the subcommands it affects, and the git version it landed in. Keys without an explicit default fall back to color.ui.

Configuration-key matrix
KeyValuesDefaultApplies toSince
color.uiauto · always · never · true · falseautoall1.5.5
color.diffauto · always · nevercolor.uidiff · show · log -p1.5.0
color.statusauto · always · nevercolor.uistatus1.5.0
color.branchauto · always · nevercolor.uibranch · branch -a1.5.0
color.grepauto · always · nevercolor.uigrep1.5.6
color.interactiveauto · always · nevercolor.uiadd -i · add -p · rebase -i1.5.0
color.decorateauto · always · nevercolor.uilog --decorate1.5.6
color.pagertrue · falsetrueany paged output1.5.6
color.adviceauto · always · nevercolor.uiadvice hints2.18
color.pushauto · always · nevercolor.uipush2.41
color.remoteauto · always · nevercolor.uifetch · remote2.21

Adjacent pages on this site that cover the surrounding ANSI / pager / CI ecosystem.