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.