Programming and IT

git log

git log shows history: which commits brought the repository to its current state. Without options the output is wordy and nearly useless, but a few flags turn it into a search tool — by author, by date, by file and even by a line of code that has disappeared.

Updated
In this article

The default output#

$ git log
commit 9f3c2a1b8d7e6f5a4c3b2a1908d7e6f5a4c3b2a1 (HEAD -> main)
Author: Maria Koval <m.koval@example.com>
Date:   Mon Sep 14 12:04:11 2026 +0300

    Reconcile warehouse stock

commit 0f4b8a3c5d6e7f8091a2b3c4d5e6f708192a3b4c
Author: Peter Soames <p.soames@example.com>
Date:   Fri Sep 11 17:22:40 2026 +0300

    Add basic cost calculation

Four lines per commit, newest first. The output opens in a pager: scroll with the arrow keys and space, quit with q. This detail trips people up more than any other: it looks as if the terminal has frozen, but it is just waiting for q.

This format tells you whose commits these are and when they were made. It does not tell you the shape of the history — for that you need other formats.

Compact formats#

git log --oneline              # hash and subject, one line per commit
git log --oneline -10          # only the last ten
git log --stat                 # plus the list of files and size of changes
git log -p                     # plus the full text of the changes
git log --graph --oneline --decorate --all   # a graph of every branch

The last line is what people usually mean by "pretty" output:

$ git log --graph --oneline --decorate --all
*   5c1a9f0 (HEAD -> main) Merge branch 'report-pdf'
|\
| * 3b7e442 (report-pdf) Add signature fields
| * a91cc05 Add print template
* | 77d0e1b Round currency values
|/
* 0f4b8a3 Add basic cost calculation

The left column shows branch lines, an asterisk is a commit. You can see that report-pdf split off from a common ancestor, someone fixed rounding in main in the meantime, and the top commit joined them.

You can shape the format precisely with --pretty:

$ git log --pretty=format:'%h %ad %an — %s' --date=short -3
9f3c2a1 2026-09-14 Maria Koval — Reconcile warehouse stock
77d0e1b 2026-09-12 Maria Koval — Round currency values
0f4b8a3 2026-09-11 Peter Soames — Add basic cost calculation

Here %h is the short hash, %ad the author date, %an the name and %s the message subject. There is no need to type this every time — set up an alias:

git config --global alias.lg "log --graph --oneline --decorate --all"

After that, git lg is enough.

Searching history#

Filters combine with each other, and that is where the command's power lies.

git log --author="Soames"                # someone's commits
git log --since="2026-09-01" --until="2026-09-15"   # over a period
git log --grep="round"                   # by message text
git log -- billing/invoice.py            # changes to one file
git log --follow -- billing/invoice.py   # including file renames
git log -S"total_sum"                    # where a string appeared or vanished
git log main..feature-pdf                # what is in the branch but not in main

-S deserves a separate word: it does not search message text but the content of the changes. It finds commits where the number of occurrences of a string changed — literally the moment a variable was introduced or removed.

$ git log -S"total_sum" --oneline -- billing/
77d0e1b Round currency values
0f4b8a3 Add basic cost calculation

The two-dot notation (main..feature-pdf) reads as "what the second ref can reach but the first cannot". It is handy before pushing a branch: you see exactly the commits you are about to propose.

Example: finding when something broke#

A line in a report started being calculated wrong, and nobody knows when. First, narrow it down by file and size of changes:

$ git log --stat --oneline -- billing/invoice.py
77d0e1b Round currency values
 billing/invoice.py | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

Then look at the whole commit:

$ git show 77d0e1b

git show prints the message and changes of a single commit — the same format as git log -p, but for one entry. If after reviewing it you need to undo the commit, the options are collected in how to undo a commit.

What git log will not show you#

History is made of commits. Anything not committed does not appear in it: you look at uncommitted edits with git status and git diff, and at stashed work with git stash list — more in the guide to git stash.

The second exception is commits that no branch can reach. After a branch reset or a rebase they drop out of git log, but they stay in the repository; you find them in the reference log, git reflog.

The third is remote branches and other people's commits you do not have yet. git log does not go to the network; run git fetch origin first, then git log origin/main.

Common mistakes#

Searching code with --grep. That filter only looks at commit messages. To search the content of changes, use -S (by number of occurrences) or -G (by a regular expression in the diff text).

File history stops at a rename. Without --follow, Git shows only what happened at the current path. The flag makes it keep searching under earlier names.

Expecting git log to show every branch. By default the command prints the history of the current branch. To see all of them, add --all; to see a specific one, pass its name: git log feature-pdf.

Mixing up the order in a range. git log feature..main and git log main..feature give different answers. On the left is what gets subtracted, on the right what gets shown. Quick check: if the output is empty, swap them.

Step-by-step plan

  1. See the shape of historygit log --graph --oneline --decorate --all; remember that q quits the pager.
  2. Set up an aliasgit config --global alias.lg with your favourite set of flags.
  3. Narrow the selection--author, --since, --grep and a path after two dashes all combine.
  4. Find a change by codegit log -S"string" -- path: the commits where the string appeared or vanished.
  5. Examine what you foundgit show <hash> in full; if needed, compare a range such as main..branch.

Start learning this in your own space

The plan goes into your repository: tick off stages, keep notes — the change history shows how far you have come.

Start the plan

Check yourself

1.Which git log flag finds commits where the number of occurrences of a line of code changed?

2.What does git log main..feature show?

3.A file's history stops where it was renamed. Which flag fixes that?

Sources

Was this helpful?

More articles

Programming and IT git commit A commit is a saved state of your project with an author, a timestamp and a message. git commit takes what you selected beforehand with git add and writes it into history as one indivisible piece. Programming and IT How to undo a commit The question "how do I undo a commit" actually hides four different ones: fix the last commit, take it back and redo it, erase several, or cancel an old commit in the middle of history. The answer depends above all on one thing — whether anyone besides you has seen that commit. Programming and IT How to learn to code from scratch You can teach yourself programming without a technical degree if you write code with your own hands from the first week instead of only watching lessons. Below is how to choose a first language, what to install, which order to take topics in and how to tell that you are really making progress. Programming and IT git merge Merging brings work from one branch into another. git merge takes the branch you name and joins its history with the current one — sometimes by just moving a pointer, sometimes by creating a separate commit, and sometimes by stopping and asking for help. Programming and IT Git branches A Git branch is a movable pointer to a commit, not a copy of your files. That is why creating one costs nothing, and the git branch command is what you use to list, create, rename and delete branches. Programming and IT git checkout Historically `git checkout` does several unrelated things at once: it moves your working copy to another branch, creates a branch and pulls a single file out of a commit. Because it was so overloaded, Git 2.23 added two separate commands — `switch` and `restore`. Here are both sides: the old way and its modern replacement.

More solutions