What do the git log flags --oneline, --graph, and --decorate each add to the output?
answer
- Three separate readability problems, three flags
- Density, topology, and orientation
- One line per commit with an abbreviated hash
- ASCII ancestry needs topological order
- Ref names printed beside their commits
basics
~20 sIn git log, --oneline prints one abbreviated-hash-plus-subject line per commit, --graph draws the commit DAG as ASCII art down the left margin, and --decorate appends the ref names — branches, tags, HEAD — that point at each commit.
solid answer
~40 sThey are three independent ways of compressing history into something readable. `--oneline` is shorthand for `--pretty=oneline --abbrev-commit`, so each commit becomes `abc1234 subject`. `--graph` draws the ancestry on the left with `*`, `|`, `/` and `\` characters, so merges and parallel branches become visible; it implies topological ordering so the lines make sense. `--decorate` annotates each commit with the refs pointing at it — `(HEAD -> main, origin/main, tag: v2.1)` — and in modern Git it is effectively on by default when writing to a terminal, with `--decorate=full` showing the complete ref paths like `refs/heads/main`. The combination people actually type is `git log --oneline --graph --decorate --all`, where `--all` widens the view from the current branch to every ref.
code
console · 8 lines$ git log --oneline --graph --decorate --all
* 8f1c2a9 (HEAD -> main, origin/main) Merge branch 'retry'
|\
| * 4b7de10 (retry) add retry backoff
| * 0c9a331 extract client factory
* | 77ab512 (tag: v2.1) bump version
|/
* 1d3e5f7 initial importgo deeper
Be able to type git log --oneline --graph --decorate --all from memory and say what each part contributes. Knowing that plain git log only shows the current branch's ancestry is the point most often missed.
Explain the mechanics behind the convenience: --oneline expands to a pretty format plus abbreviation, --graph implies topological ordering, and decoration defaults to auto so pipelines stay clean.
Show that you shape output deliberately — custom --pretty=format for reporting, --first-parent to read a mainline, and awareness that graph rendering is the expensive part on large histories.
Connect it to practice: readable history is a product of commit and merge conventions, and the log view a team standardises on should match the topology their branching model actually produces.
## The problem these flags solve Plain `git log` prints a paragraph per commit: full hash, author, date, blank line, indented message. That is fine for reading one commit and useless for understanding shape. The three flags below turn the same traversal into something you can scan. ## `--oneline` `--oneline` is defined as shorthand for `--pretty=oneline --abbrev-commit`. Each commit collapses to a single line: an abbreviated hash followed by the subject (the first line of the commit message). Git chooses an abbreviation length long enough to stay unambiguous in that repository, which is why you see seven characters in small repos and more in large ones. The abbreviated hash is a real revision name — you can paste it into `git show`, `git branch`, or `git reset`. This is also the flag that makes commit-message discipline visible. If your history is a wall of "fix", `--oneline` output is where that becomes everyone's problem. ## `--graph` `--graph` prefixes each line with an ASCII drawing of the commit ancestry: `*` for a commit, `|` for a continuing line of descent, and `/` and `\` where branches fork and merge. A merge commit shows two (or more) lines converging into it. The important mechanical detail is that `--graph` implies topological ordering. Left to itself, `git log` lists commits in reverse chronological order, which would draw nonsense — a child could appear above an ancestor's other lineage in a way the ASCII art cannot represent. Topological ordering guarantees no commit is shown before its descendants, so the drawing is coherent. That is also why the ordering you see with `--graph` sometimes differs from the ordering without it. A graph of a busy repository is still a thicket. `--first-parent` is the usual antidote: it follows only the first parent of each merge, which on a branch that receives merges reduces the picture to "what landed on this branch, in order". ## `--decorate` A commit hash tells you nothing about which branch or tag is sitting on it. `--decorate` appends the refs pointing at each commit, in parentheses: `(HEAD -> main, origin/main, tag: v2.1)`. The arrow after HEAD shows which branch HEAD is attached to; a bare `(HEAD)` means detached. The modes are `--decorate=short` (strip the `refs/heads/`, `refs/tags/`, `refs/remotes/` prefixes — the readable default), `--decorate=full` (print the complete ref path, useful when a branch and a tag share a name), and `--decorate=no`. In modern Git the effective default is `auto`, which decorates when output goes to a terminal and stays quiet when piped into another program, so scripts are not surprised by extra text. The `log.decorate` configuration key sets your preference permanently. ## `--all` and why it usually joins the party By default `git log` starts from HEAD and walks backwards, so you only see your current branch's ancestry. `--all` starts the traversal from every ref, which is what makes the graph show other branches and the decorations meaningful. `git log --oneline --graph --decorate --all` is the canonical "show me the repository" command, and many people alias it. ## Choosing among them They compose freely and address different questions: `--oneline` for density, `--graph` for topology, `--decorate` for orientation. When you only want density, drop the graph — it is the expensive and visually noisy part on a large history. When you want a custom shape instead, `--pretty=format:` lets you build your own line from placeholders such as `%h` (abbreviated hash), `%an` (author name), `%ad` (author date), `%s` (subject), and `%d` (the decoration), combined with `--date=short` or `--date=relative` to control the date rendering. ## What an interviewer is really checking That you read history rather than scrolling past it. Anyone can recite the flags; the follow-through that lands is knowing that `--graph` forces topological order, that decoration is on by default only for terminals, and that without `--all` you are looking at one branch's ancestry rather than the repository.
- Why does --graph change the order commits appear in?Because it implies topological ordering. Default log output is reverse chronological, which can interleave unrelated lines of development in a way ASCII art cannot draw coherently. Topological order guarantees a commit never appears before its descendants, so the drawn lines connect correctly, at the cost of no longer being strictly by date.
- What does --all add, and what does it still leave out?It starts the traversal from every ref rather than just HEAD, so other branches, tags and remote-tracking refs appear. It still shows only reachable history: commits orphaned by a reset or rebase are not included, since no ref points at them. Add --reflog to bring reflog entries in as starting points.
- Why is decoration suppressed when you pipe git log into another command?The effective default is auto, which decorates only when standard output is a terminal. Scripts parsing log output would otherwise receive extra parenthesised text that changes as branches move. Pass --decorate explicitly when you want it in a pipeline, or set log.decorate to pin the behaviour.
saying these in an interview costs you the question
- Thinks --oneline truncates the commit message body meaningfully rather than showing the subject
- Believes git log shows all branches by default
- Says --decorate changes which commits are listed
- Assumes graph output is still strictly reverse-chronological
- Treats the abbreviated hash as unusable as a revision name