Review¶
log
¶
Filter and sort¶
$ git log [-n COUNT]
¶lists the commit history of the current branch.
-n
limits the number of commits to the specified number.
$ git log [--after="YYYY-MM-DD"] [--before="YYYY-MM-DD"]
¶Commit history filtered by date.
Relative specifications such as
1 week ago
oryesterday
are also permitted.filters the commit history by author.
It is also possible to search for several authors at the same time, for example:
$ git log --author="VEIT|VSC"
$ git log --grep="TERM" [-i]
¶filters the commit history for regular expressions in the commit message.
-i
ignores upper and lower case.
$ git log -S"FOO" [-i]
¶filters commits for specific lines in the source code.
-i
ignores upper and lower case.
$ git log -G"BA*"
¶filters commits for regular expressions in the source code.
$ git log -- PATH
¶filters the commit history for specific files.
$ git log MAIN..FEATURE
¶filters for different commits in different branches, in our case between the
MAIN
andFEATURE
branches.However, this is not the same as
git log FEATURE..MAIN
. Let’s take the following example:A - B main \ C - D feature
$ git log MAIN..FEATURE
shows changes in
FEATURE
that are not contained inMAIN
, that is, commitsC
andD
.$ git log FEATURE..MAIN
shows changes in
MAIN
that are not contained inFEATURE
, that is, commitB
.$ git log MAIN...FEATURE
shows the changes on both sides, that is, commits
B
,C
andD
.
$ git log --follow PATH/TO/FILE
¶This ensures that the log shows changes to a single file, even if it has been renamed or moved.
You can activate
--follow
for individual file calls by default by activating thelog.follow
option in your global configuration:$ git config --global log.follow true
Then you no longer have to enter
--follow
, but only the file name.$ git log -L LINE_START_INT|LINE_START_REGEX,LINE_END_INT|LINE_END_REGEX:PATH/TO/FILE
¶$ git log -L :FUNCNAME_REGEX:PATH/TO/FILE
¶With the -L option, you can perform a refined search by checking the log of only part of a file. This function allows you to thoroughly search through the history of a single function, class or other code block. It is ideal for finding out when something was created and how it was changed so that you can correct, refactor or delete it with confidence.
For more comprehensive investigations, you can also track multiple blocks. You can use multiple
-L
options at once.$ git log --reverse
¶The log usually displays the latest commit first. You can reverse this with
--reverse
. This is particularly useful if you are analysing with the-S
and-G
options already mentioned. By reversing the order of the commits, you can quickly find the first commit that added a specific string to the codebase.
View¶
$ git log --stat --patch|-p
¶--stat
A summary of the number of changed lines per file is added to the usual metadata.
--patch|-p
adds the complete commit diff to the output.
$ git log --oneline --decorate --graph --all|FEATURE
¶display the history graph with references, one commit per line.
--oneline
One commit per line.
--decorate
The prefixes
refs/heads/
,refs/tags/
andrefs/remotes/
are not output.--graph
The log usually smoothes historical branches and displays commits one after the other. This hides the parallel structure of the history when merging branches.
--graph
displays the history of the branches in ASCII format.--all|FEATURE
--all
shows the log for all branches;FEATURE
only shows the commits of this branch.
reflog
¶
With git reflog, your Git repository is not checked a second time. Instead, it displays the reference log, a record of all commits made. The reflog not only tracks changes to a branch, it also records changes to the current commit, branch changes, rebasing, etc. You can use it to find all unreachable commits, even those on deleted branches. This allows you to undo many otherwise destructive actions.
Let’s look at the basics of using reflog and some typical use cases.
Warning
The reflog is only part of your local repository. If you delete a repository and clone it again, the new clone will have a fresh, empty reflog.
Show the reflog for HEAD
¶
$ git reflog
¶If no options are specified, the command displays the reflog for
HEAD
by default. It is short forgit reflog show HEAD
. git reflog has other subcommands to manage the log, but show is the default command if no subcommand is passed.
1$ git reflog
212bc4d4 (HEAD -> main, my-feature-branch) HEAD@{0}: merge my-feature-branch: Fast-forward
3900844a HEAD@{1}: checkout: moving from my-feature-branch to main
412bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2}: commit (amend): Add my feature and more
5982d93a HEAD@{3}: commit: Add my feature
6900844a HEAD@{4}: checkout: moving from main to my-feature-branch
7900844a HEAD@{5}: commit (initial): Initial commit
The output is quite dense.
Each line is a reflog entry, the most recent first.
The lines start with the abbreviated SHA of the corresponding commit, for example
12bc4d4
.The first entry is what
HEAD
currently refers to:(HEAD -> main, my-feature)
.The names
HEAD@\{N}
are alternative references for the specified commits.N
is the number of returning reflog entries.remaining text describes the change. Above you can see several types of entries:
commit: MESSAGE
for commitscommit (amend): MESSAGE
for a commit changecheckout: moving from SRC TO DST
for a branch change
There are many other possible types of entries. The text should be descriptive enough that you can understand the process without looking it up in the documentation. In most cases, you will want to look through such reflog entries to find the corresponding commit SHA.
Show the reflog for a branch¶
You can focus on entries for a single branch by using the explicit subcommand
show
and the branch name:
$ git reflog show my-feature-branch
12bc4d4 (HEAD -> main, my-feature-branch) my-feature-branch@{0}: commit (amend): Add my feature and more
982d93a my-feature-branch@{1}: commit: Add my feature
900844a my-feature-branch@{2}: branch: Created from HEAD
Show timestamps of the entries¶
If you need to distinguish between similarly titled changes, the timestamps can
help. For relative timestamps you can use --date=relative
:
$ git reflog --date=relative
12bc4d4 (HEAD -> main, my-feature) HEAD@{vor 37 Minuten}: merge my-feature-branch: Fast-forward
900844a HEAD@{vor 37 Minuten}: checkout: moving from my-feature-branch to main
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{vor 37 Minuten}: commit (amend): Add my feature and more
982d93a HEAD@{vor 38 Minuten}: commit: Add my feature
900844a HEAD@{vor 39 Minuten}: checkout: moving from main to my-feature-branch
900844a HEAD@{vor 40 Minuten}: commit (initial): Initial commit
And for absolute timestamps you can also use --date=iso
:
$ git reflog --date=iso
12bc4d4 (HEAD -> main, my-feature) HEAD@{2024-01-11 15:26:53 +0100}: merge my-feature-branch: Fast-forward
900844a HEAD@{2024-01-11 15:26:47 +0100}: checkout: moving from my-feature-branch to main
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2024-01-11 15:26:11 +0100}: commit (amend): Add my feature and more
982d93a HEAD@{2024-01-11 15:25:38 +0100}: commit: Add my feature
900844a HEAD@{2024-01-11 15:24:37 +0100}: checkout: moving from main to my-feature-branch
900844a HEAD@{2024-01-11 15:23:56 +0100}: commit (initial): Initial commit
Passes all options that git log
supports¶
git reflog show
has the same options as git log
. For example, you can
use --grep
to search for commit messages that mention my feature
without case-sensitivity:
$ git reflog -i --grep 'my feature'
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{0}: merge my-feature: Fast-forward
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2}: commit (amend): Add my feature and more
982d93a HEAD@{3}: commit: Add my feature
Note the expiry of entries¶
Reflog entries expire after a certain time when Git runs the automatic gc process for your repository. This expiration time is
controlled by two gc.*
options:
gc.reflogExpire
The general expiration time, which is set to 90 days by default.
gc.reflogExpireUnreachable
The expiry time for entries relating to commits that can no longer be reached is set to 30 days by default.
You can increase these options to a longer time frame, but this is rarely useful.