This post is copied from my page on Floppy.
Updated on 19 August: Today I learned about
--reflogswitch. No more subshell madness.
One might think of git as a forest, and in forests there are usually a lot of logs. Git, on the other hand, only has three of them: log, shortlog, and reflog.
Did you know Git can summarize commit ranges for you?
Try it out with git shortlog HEAD~10.. and it'll give you a nice and quick summary.
As a bonus, it doesn't even defer to an LLM, which is a massive win.
git-shortlog is a postprocessor for the "main" log output,
leaving only summary lines from the commits and grouping by author
(other options are available, with grouping by committer having its own short option, -c).
Reflogs are used when commits are mentioned with @{N} suffix,
where N denotes the position of the entry in the reflog, relative to the most recent one.
The most important of reflogs is of course the HEAD reflog,
which allows using HEAD@{N} references and holds the history of HEAD,
including all rebase steps and dropped and amended commits.
For example, one can use HEAD@{1} after fast-forward-merge to refer to the previous HEAD.
Note that reflogs are appended to,
and checkouting to HEAD@{N} will append new entries to the reflog,
so the backreference numbers are offset by one.
It is possible to manipulate the reflog manually with subcommands:
expire: prune old entries; not typically called manually, git gc calls it,delete: redact specific entries,write: append new entries,drop: scrub the selected reflog.The write subcommand might be useful for custom git-based tooling.
Stash stack is implemented using refs/stash reflog.
The reflog is also accessible with git log --walk-reflogs HEAD.
git log is the "main" log.
It is probably The Log people will think of when you mention git log, and it holds commit graph.
This graph is sometimes called "commit history" or simply "history".
git log command has dozens of options.
Some of them might even seem useful.
Decision paralysis time! Here's a filtered list of cool options:
-- ../some/path: show only commits affecting certain path.
This option should come after all other options
--oneline: show only commit descriptions and short hashes
--graph --decorate: show commit graph as literal graph.
Combine with --oneline or --format=format:"..." for better view
--topo-order, --date-order, --author-date-order: commit ordering mode.
Use --topo-order with --graph for a nicer-looking graph
--all: show all reachable commits
(all local and remote branches, all local and remote tags, most recent stash)
--reflog[1]: show ALL commits that git knows about.
The command in subshell lists every commit under the sun,
and when combined with --graph options shows a tree visualisation of a reflog
(without @{N} numbers, but still)
--grep=<pattern>: search for commit text.
--all-match makes git log search for commits satisfying all instead of any patterns.
--invert-grep does what it says on the tin.
-i, -E, -F, and -P are the same as in normal grep.
-S<regex> and -G<regex> search for changes of <regex> in code
(S: commits that change number of per-file occurences of regex;
G: commits whose hunks contain regex)
--patch: show commit diffs. Allows viewing commit ranges nicely
--reverse: reverse order. Can be useful with --patch to show in more readable order
git diff options, like --word-diff and -w, if combined with --patch
git show options, like --stat and --shortstat
I have the following aliases:
l = "log --topo-order --graph --decorate --format=format:\"...\""
ll = "!git l --all"
lr = "!git ll --reflog"
lo = "!git l --oneline"
llo = "!git ll --oneline"
lro = "!git lr --oneline"
The --format=format:"..." bit is the only uncovered one.
There is a lot of formatting options,
and Git gives a lot of freedom in terms of styling.
If you have some spare time, try tweaking the format to your pleasure.
Format string I use is a middle-ground between --oneline and default format,
and it shows commit id, author, date, relative date and subject
(with spaces converted to line breaks for readability):
%C(bold blue)%h%C(reset)
%C(dim italic cyan)%aD%C(reset)
%C(dim white)%aN%C(reset)
%C(green)(%ar)%C(reset)%C(yellow)%d%C(reset)%n
%C(white)%s%C(reset)
I don't use it that often, as I have come to realise
that I don't usually need that many information on my screen,
and --oneline has a good everyday balance for me.
Be careful with formatting strings, as some options don't respect .mailmap files.
Use %aN, %aE, %aL, %cN, %cE, %cL
instead of the ones with the lowercase n, e, and l to avoid seeing outdated information.
This previously mentioned using $(git rev-list -g --all).
Git supports --reflog option since version 2.2, released in 2015,
and that option is equivalent to the subshell snippet,
while lacking its obvious limitation of kernel argument length limit. ↩︎