--- topic: git-log-format source_keys: - git-scm-log-docs - git-scm-diff-docs --- ## Named Format Presets (`--format` / `--pretty`) | Name | Output | |---|---| | `oneline` | ` ` | | `short` | hash, author, title | | `medium` | hash, author, date, full message (default) | | `full` | adds committer | | `fuller` | separate author/committer dates | | `reference` | `<abbrev> (<title>, <date>)` — for use in commit messages | | `email` | RFC 2822 email format | | `raw` | full object as stored in the object database | | `format:<str>` | custom template with placeholders | ## Custom Format Placeholders **Commit identity:** | Placeholder | Meaning | |---|---| | `%H` | full commit hash | | `%h` | abbreviated commit hash | | `%T` | tree hash | | `%t` | abbreviated tree hash | | `%P` | full parent hashes | | `%p` | abbreviated parent hashes | **Author:** | Placeholder | Meaning | |---|---| | `%an` | author name | | `%aN` | author name (mailmap-resolved) | | `%ae` | author email | | `%aE` | author email (mailmap-resolved) | | `%ad` | author date (respects `--date=`) | | `%ar` | author date, relative | | `%at` | author date, UNIX timestamp | | `%ai` | author date, ISO 8601-like | | `%aI` | author date, strict ISO 8601 | | `%as` | author date, short (YYYY-MM-DD) | **Committer:** | Placeholder | Meaning | |---|---| | `%cn` | committer name | | `%ce` | committer email | | `%cd` | committer date (respects `--date=`) | | `%cr` | committer date, relative | | `%ct` | committer date, UNIX timestamp | | `%ci` | committer date, ISO 8601-like | | `%cs` | committer date, short | **Message:** | Placeholder | Meaning | |---|---| | `%s` | subject (first line) | | `%f` | sanitized subject (filename-safe) | | `%b` | body (everything after blank line following subject) | | `%B` | raw body (subject + body) | | `%N` | commit notes | **Refs and decorations:** | Placeholder | Meaning | |---|---| | `%d` | ref names (like `--decorate`) | | `%D` | ref names without surrounding parentheses | | `%S` | ref name by which commit was reached (requires `--source`) | | `%(decorate[:opts])` | custom decorated refs; options: `prefix=`, `suffix=`, `separator=`, `pointer=`, `tag=` | | `%(describe[:opts])` | like `git describe`; options: `tags=`, `abbrev=`, `match=`, `exclude=` | **GPG signature:** | Placeholder | Meaning | |---|---| | `%G?` | status: `G`=good, `B`=bad, `U`=unknown, `X`=expired, `R`=revoked, `N`=no signature | | `%GS` | signer name | | `%GK` | signing key ID | **Trailers:** ```text %(trailers[:key=<k>][,only][,separator=<s>][,unfold][,keyonly][,valueonly]) ``` **Formatting / color:** | Placeholder | Meaning | |---|---| | `%n` | newline | | `%%` | literal `%` | | `%Cred` / `%Cgreen` / `%Cblue` / `%Creset` | terminal colors | | `%C(<spec>)` | color per git-config spec | | `%<(<n>[,trunc])` | right-pad field to width n | | `%>(<n>)` | left-pad to width | **Reflog** (requires `-g` / `--walk-reflogs`): | Placeholder | Meaning | |---|---| | `%gD` | reflog selector (e.g. `refs/stash@{1}`) | | `%gd` | shortened reflog selector | | `%gs` | reflog subject | ## Pickaxe Search: -S and -G **`-S<string>`** — finds commits where the **count** of `<string>` changed (i.e. the string was added or removed net). Does not match commits where the string merely appears in a diff hunk without a count change. ```bash git log -S"my_function" git log -S"my_function" --pickaxe-regex # treat as POSIX ERE git log -S"my_function" --pickaxe-all # show all files in matching changesets ``` **`-G<regex>`** — finds commits where any added or removed **line** in the patch matches `<regex>`. Broader than `-S`: matches whenever the pattern appears in diff text regardless of count. ```bash git log -G"frotz\(nitfol" ``` **Critical distinction:** given a diff that removes one occurrence of `foo` and adds one occurrence of `foo` (net change = 0): - `-S"foo"` — does **not** match (count unchanged) - `-G"foo"` — **matches** (pattern appears in patch text) Binary files are searched by `-S`; ignored by `-G` unless `--text` is supplied. ## --diff-filter (full table) Selects commits (in `git log`) or files (in `git diff`) by change type: | Letter | Meaning | |---|---| | `A` | Added | | `C` | Copied | | `D` | Deleted | | `M` | Modified | | `R` | Renamed | | `T` | Type changed (regular file ↔ symlink ↔ submodule) | | `U` | Unmerged (conflict) | | `X` | Unknown (indicates a git bug) | | `B` | Pairing broken | Lowercase letters **exclude** that type: ```bash git log --diff-filter=ad # exclude added and deleted files git log --diff-filter=M # only show commits with modified files ``` `C` and `R` only appear when copy/rename detection is enabled (`-C`, `-M` flags or `diff.renames` config). ## -L — Line Range History (full syntax) Traces the evolution of a specific range of lines or a named function through commits. Implies `--patch`. ```bash git log -L 10,20:file.txt git log -L /start_pattern/,/end_pattern/:file.txt git log -L :myfunction:src/app.c git log -L /init/,+15:config.py # 15 lines after first match of /init/ ``` Range formats: | Format | Meaning | |---|---| | `<n>` | Absolute line number (1-based) | | `/<regex>/` | First line matching regex from previous range end | | `^/<regex>/` | First line matching regex from file start | | `+<n>` / `-<n>` | Offset relative to `<start>` (end position only) | Limitations: incompatible with `--raw`, `--numstat`, `--shortstat`, `--name-only`, `--name-status`, `--check`. Cannot use pathspec limiters alongside `-L`. ## Graph and Ancestry Filters ```bash git log --first-parent # at merges, follow only first parent (mainline evolution) git log --merges # only merge commits (≥2 parents); equivalent to --min-parents=2 git log --no-merges # only non-merge commits; equivalent to --max-parents=1 git log --ancestry-path D..M # only commits actually on the path from D to M git log --min-parents=<n> # include only commits with ≥ n parents git log --max-parents=<n> # include only commits with ≤ n parents ``` `--ancestry-path` is significant: without it, `D..M` includes all commits reachable from M but not D — including side branches that merged into the path. With it, only commits directly between D and M are shown. ## git diff — Output Control ### --stat ```bash git diff --stat # diffstat: file names + ± bar git diff --stat=<width>,<name-width>,<count> git diff --compact-summary # alongside --stat: shows new/gone, +x/-x (executable), +l (symlink) git diff --numstat # machine-readable: <added>\t<deleted>\t<path>; - for binary ``` ### --name-only / --name-status ```bash git diff --name-only # only filenames, one per line git diff --name-status # status letter + filename per line ``` `--name-status` uses the same status letters as `--diff-filter`. ### --word-diff ```bash git diff --word-diff # inline word-level diff with [-removed-] {+added+} markers git diff --word-diff=color # color only, no markers git diff --word-diff=porcelain # machine-readable: +/- prefixed lines, ~ for newlines git diff --word-diff-regex=<re> # define what counts as a "word" ``` ### Whitespace Flags | Flag | Effect | |---|---| | `-b` / `--ignore-space-change` | Treat any run of whitespace as equivalent; ignore trailing whitespace | | `-w` / `--ignore-all-space` | Ignore all whitespace completely | | `--ignore-space-at-eol` | Ignore whitespace at end-of-line only | | `--ignore-blank-lines` | Ignore changes consisting entirely of blank lines | | `-I<regex>` / `--ignore-matching-lines=<re>` | Ignore changes where all changed lines match regex |