Git

What Is Git Log? A Quick Look at Git History

What Is Git Log? A Quick Look at Git History

Somebody changed that config file last month and nobody remembers who. Or a bug showed up in the latest release and you need the commit that started it.

git log is where both searches begin. It lists the commits reachable from a revision, newest first, and it never alters the repository.

Each entry shows a commit hash, an author, a date, and a commit message. That is enough to audit changes, trace a regression, or compare a branch against main.

The manual on git-scm.com describes the output as a set operation. You get the commits reachable from the revisions you name, minus any reachable from a revision prefixed with ^.

Range notation, path limits, and filters all work by narrowing that one set.

What Is git log?

YouTube player

With no arguments, git log starts at HEAD, follows the parent links of each commit through a Git repository, and prints what it finds through a pager until it reaches the first commit. Nothing in the repository changes.

The syntax is git log [<options>] [<revision-range>] [[--] <path>…].

None of it is required. Options change what gets shown. The revision range decides where the walk starts and stops. A path (or several) limits the output to commits that touch it.

The git-log manual last changed in Git 2.56.0, dated 2026-09-28 (git-scm.com). Run git --version to see which release you have.

How git log differs from similar commands

YouTube player

git show prints a single commit together with its patch. git reflog records where HEAD and branch tips used to point, which is a different thing from commit ancestry. And git shortlog groups log output by author, so it suits release announcements better than daily digging.

Why is GitHub the heart of open source?

Uncover GitHub statistics: developer community growth, repository trends, collaboration patterns, and the platform that powers modern software development.

Explore GitHub Data →

By default, git log prints no diff at all, according to the git-log manual. Add -p or --stat when you want to see what each commit changed.

How Do You Read the Default git log Output?

YouTube player

The default medium format prints the newest commit first, and every entry holds a commit hash, an author, a date, and a message.

Anatomy of one entry

  • The commit line holds the full hash, plus ref names such as (HEAD -> main, origin/main) when output goes to a terminal.
  • The author line gives the name and email of whoever wrote the change.
  • The date is the author date, shown in the original time zone.
  • Last comes the message, subject line first and then the body, indented by 4 spaces.

The full hash is a 40-byte hexadecimal object name (git-log manual, Git 2.56.0). You rarely type all of it, since any unique leading part works as a commit hash in later commands.

The names in parentheses are labels pointing at that commit. HEAD -> main tells you which branch is checked out.

Merge commits get one extra line, Merge:, placed before the Author line. It lists the abbreviated hashes of the parents.

Looking to sharpen your Git skills? Branching, merging, rebasing, and everything else you need - including git rebase, git stash, and commit workflows - is on one page in the Git Cheat Sheet.

Navigating the pager

Long output goes through a pager, usually less, so the log stops after the first screen.

  • Space moves to the next page and b goes back one
  • j and k move a single line down or up
  • q quits

Use git --no-pager log to print everything in one go. That suits scripts and piping.

How to Format git log Output

YouTube player

Most days --oneline is enough. It prints one abbreviated hash and subject per commit. When you need other fields, --pretty or --format take over.

Compact views

--oneline is shorthand for --pretty=oneline --abbrev-commit.

--graph draws branch and merge lines down the left side. It implies --topo-order, so commit order can differ from a plain log.

▶ GIT EXPLAINED

If you commit, branch, or merge code every day, it helps to know how Git came to be. This video covers how Linus Torvalds created Git in just 10 days after a license dispute and explains how its data model actually works.

Linus Torvalds Built Git in Days Out of Spite
Built in 10 Days Out of Spite. Git and its data model explained in plain language.

--decorate prints ref names next to commits. It is already on when output goes to a terminal, so you will rarely type it.

Abbreviated hashes default to 7 hexadecimal digits and grow as the repository gets larger (git-scm.com, pretty-formats manual).

Built-in pretty formats

FormatFields shownBest for
onelineHash and subjectScanning long history
shortHash, author, subjectQuick author check
medium (default)Hash, author, date, full messageEveryday review
fullerAuthor and committer, both datesRebased or cherry-picked work

Custom format strings

The --format option takes placeholders. %h is the abbreviated hash, %an the author name, %ar the relative date, %s the subject, and %d the ref names.

A working example is git log --format="%h %an %ar %s".

Dates follow --date, which accepts relative, short, iso, human, and format: with a strftime string. The log.date config variable sets the default.

One quirk. format: separates entries, so the last line has no trailing newline. tformat: terminates every entry, and any string containing a % placeholder is treated as tformat: automatically.

How to Filter Commits by Author, Date, Message and Count

YouTube player

The options that do most of the work are --author, --since with --until, --grep, --no-merges, and -n. They stack, so combining them narrows the result further.

By author and date

--author takes a regular expression matched against the author header, so it catches names and emails. Pass it several times and a commit matching any of the patterns is shown.

--committer does the same on the committer header. After a rebase or cherry-pick, that header differs from the author.

--since and --until accept dates such as “2 weeks ago”, and “today” means the last midnight.

--since stops walking at the first commit older than the date. --since-as-filter visits every commit in the range instead, so a commit with an out-of-order timestamp further back still gets checked.

By message

--grep matches a regular expression against the commit message.

  • Several --grep flags match any pattern, unless --all-match requires every one.
  • --invert-grep keeps commits that do not match.
  • Add -i to ignore case.
  • -E and -F switch to extended regex or fixed strings.

By type and count

Merge commits have more than one parent, and Git creates them when you run git merge. --no-merges hides them, and --merges shows only them.

-3 shows the 3 newest commits that pass every other filter.

--skip=10 drops the first 10.

Filters that hide merges also hide the story of how a branch landed. Keep merges visible when you audit what reached the main branch.

How Do Revision Ranges and Paths Change What git log Shows?

YouTube player

A revision range sets which commits git log walks, and a path restricts the output to commits that modify it. With no range given, git log defaults to HEAD (git-scm.com, git-log manual).

Two-dot and three-dot ranges

NotationSelectsExample
A..BReachable from B, not from Agit log main..feature
A…BReachable from either side, not bothgit log main...feature
B –not ASame as A..B, written outgit log feature --not main

You can omit one end and it defaults to HEAD. origin.. answers what you committed since your branch forked from origin.

Writing git log A..B C..D does not produce two ranges. It names a single set of commits reachable from B or D but from neither A nor C, per gitrevisions.

Ends can be any ref. Tags work as range endpoints, so git log v2.5.. lists everything since that release.

  • --all starts from every ref plus HEAD, and --branches, --tags and --remotes narrow that to one ref type.
  • --first-parent follows only the first parent at each merge, which gives an overview of a topic branch.

Limiting by file or directory

Put a path after -- to keep only commits that touch it, as in git log -- src/. The separator is required when a path could be mistaken for a branch name.

Combine a path with a date filter for a fast review. git log --since="2 weeks ago" -- gitk is the manual’s own example.

Paths work with ranges too. git log main..feature -- README.md shows only the commits on feature that changed that file.

How to See What Changed in Each Commit and Search Code History

YouTube player

Add -p to print each commit’s patch, or --stat for a per-file summary. To find the commit that introduced a change, reach for -S, -G, or -L.

Showing diffs and file lists

Patch output comes from the same machinery as git diff, so its display options carry over to the log.

  • -p gives the full patch for every commit.
  • --stat lists changed files with insertion and deletion counts.
  • --name-only prints file names and nothing else.
  • --name-status adds a status letter to each name (A added, M modified, D deleted, R renamed).

Status letters also drive --diff-filter. git log --diff-filter=A --name-status lists only the files each commit added.

With a path, -p shows the diff for that path only. Add --full-diff to see the whole commit diff for commits that touch it.

Finding when code appeared or changed

-S "string" matches commits that change how many times the string occurs in a file.

-G "regex" matches commits whose patch has an added or removed line matching the expression.

The git-diff manual gives the sharpest example. A call to frotz is rewritten in place, so -G finds the commit while -S misses it, because the number of occurrences stayed the same.

-L traces a line range or a function through history, as in git log -L :main:main.c. It implies -p.

git log --follow -p -- path/to/file keeps listing a file’s history across renames.

Which git log Command Answers Which Question?

YouTube player

Start from the question you have, not the flag you remember. Who, when, what, and where each lead to a different set of options.

QuestionCommandReturns
What did I commit today?git log --author="Ana" --since=today --onelineYour commits since midnight
What is on this branch but not on main?git log main..HEAD --onelineCommits unique to the branch
When was this string added or removed?git log -S"timeout" --onelineCommits that changed its count
How did this function evolve?git log -L :parse_args:cli.pyPatches touching that function
Which commit added this file?git log --diff-filter=A -- path/to/fileThe commit that created it

If you know the exact string, use -S. A pattern or an edited line fits -G better. And when the target is a function or a line range, go with -L.

Run the query with --oneline first. Once the candidate list is short, drop it and add -p to read the actual change.

When Does git log Not Show What You Need?

It misses commits that are unreachable from your starting point, and it hides some behind history simplification. File and line tracing also come with hard limits.

Commits that are not reachable

git log only lists commits reachable from the revisions you give it. A deleted branch, or a branch tip moved back with git reset, drops commits out of every normal range.

git reflog show is an alias for git log -g --abbrev-commit --pretty=oneline, so the same options work on it (git-reflog manual).

The recovery window is short. Reflog entries expire after 90 days by default, and after 30 days when the commit is unreachable from the branch tip (git-reflog manual).

History simplification hides commits

With a path, git log simplifies history. The default mode prunes side branches when a merge result is identical, so a commit you know touched the file can be missing.

--full-history follows every parent of a merge, and --simplify-merges then drops needless merges from that full view. --show-pulls adds the merge commits that first brought a change onto the branch.

The catch is that --simplify-merges walks the entire history before it returns a single result. On a very large repository that gets slow.

Merge commits and diffs

Merge commits print no diff unless you pass -m, -c, --cc, or another --diff-merges variant.

They also stay out of -S and -G results without one, so a change that exists only in a conflict resolution can hide from a search. The exception is --first-parent, which turns on first-parent diffs by default.

File and line limits

  • --follow works on one file, not on a directory.
  • -L accepts no path limiters, starts from a single revision, and does not support --stat formats.

Rename detection also skips its exhaustive comparison above 1000 files by default (diff.renameLimit).

For the author of each current line, git blame answers directly. git log -L shows the full chain of changes behind those lines.

How to Set Defaults and Aliases for git log

Date style, short hashes, shortcuts, and saved formats cover most needs. They map to log.date, log.abbrevCommit, alias.<name>, and pretty.<name>.

Each one lives in a config file that git config reads and writes.

  1. Choose the scope. --global writes to ~/.gitconfig, and without a scope flag the value goes to the repository’s .git/config.
  2. Set a date style with git config set --global log.date short.
  3. Turn on short hashes everywhere with git config set --global log.abbrevCommit true.
  4. Add a shortcut with git config set --global alias.lg "log --oneline --graph --decorate".
  5. Save a format with git config set --global pretty.brief "format:%h %an %ar %s", then run git log --pretty=brief.
  6. Check the result with git config list --show-origin, which prints each value next to the file it came from.

Git reads system, global, then local files, and the last value found wins. A repository setting beats your global one.

Per the 2.56.0 manual, the older git config <name> <value> form is deprecated in favor of get, set, and list. If git config set is rejected, your Git predates the subcommands and the old form still applies.

Two more defaults are worth knowing. log.decorate falls back to auto when unset, and --no-abbrev-commit on the command line overrides log.abbrevCommit.

Anything saved in .git/config stays on your machine. Teammates do not receive it through commits.

git log FAQ

How do I see commits on a remote branch?

Run git log origin/main, swapping in your remote and branch names. The output reflects your last fetch, so run git fetch first.

To list only what you have not merged yet, use git log main..origin/main.

How do I count commits per author?

Use git shortlog -sn. The -s flag prints only counts and -n sorts by them, which plain git log cannot do.

For release announcements, git shortlog v2.0..HEAD groups commit subjects under each author instead.

How can I check whether commits are signed?

Add --show-signature. Git passes each signature to gpg --verify and prints the result under the commit.

For a compact view, --format="%h %G? %s" prints one status letter per commit, such as G for good, B for bad, and N for unsigned. Set log.showSignature to make it the default.

How do I save git log output to a file?

Redirect it with git log --oneline > history.txt. Git only colors output going to a terminal under the default auto setting, so the file stays free of escape codes.

A changelog draft works the same way. Try git log --format="%s" v1.0..HEAD > notes.txt.

What to Do After git log Finds the Commit

Once git log surfaces the commit, inspect it first, then undo it with a new commit instead of rewriting history.

The order matters because each step lowers the risk of the next. Read the full patch with git show, trace the same lines with git log -L, and only then undo the change with git revert.

A later commit that touches those lines turns a clean revert into a conflict, so the trace comes before the undo.

Reverting a commit in Git adds an inverse commit, which leaves the history other developers already pulled intact. The price is a longer log, since the original commit and its inverse both stay visible.

This sequence fits a commit on a shared branch (position verified 1 October 2026). A commit that exists only on your local branch can be dropped with a reset instead.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.