Git Reflog



The git reflog command keeps track of every change made in the references (branches or tags). This mechanism is called reference logs, or "reflog". Different Git commands take a parameter for specifying a reference or "ref" like git merge, git reset, git checkout... . This parameter serves to point to a commit.

The "reflog" mechanism takes back even commits that are not referenced by any refs. It tracks when the refs are updated in the local repository. Reflogs are saved in directories under the local repository .git directory.

When rewriting history, the reflog holds information about the past states of branches and makes it possible to return to that state if required.


The Basic Usage of Git Reflog Command

The common use of the git reflog command is as follows:

$ git reflog 

This is a shortcut that is equal to:

$ git reflog show HEAD 

The command above will output the HEAD reflog. The output looks similar to the following:

c6db2c8 HEAD@{0}: commit: changing content 
90bb007 HEAD@{1}: checkout: moving from master to git_reflog_branch
90bb007 HEAD@{2}: commit: adding more content
90bb007 HEAD@{3}: reset: moving to HEAD
90bb007 HEAD@{4}: commit: modified content of reflog_file_demo
1a03d4b HEAD@{6}: commit (initial): initial commit

Reflog References

By default, the git reflog command will output the reflog of HEAD ref. The HEAD is a reference to the currently active branch. The reflog mechanism works on all refs. A Git ref can be accessed using the name@{qualifier} syntax. Additionally, to HEAD refs, we can reference other refs like branches, remotes, tags, GiT stash.

To show the entire reflog of all the references, execute the following command:

$ git reflog show -all

If you want to see just the reflog of a specific branch, you can pass the branch's name as a parameter to the git reflog show command. The command bellow outputs a reflog of 'demo_reflog_branch':

$ git reflog show demo_reflog_branch
128be37 demo_reflog_branch@{1}: commit: Add more content
eed1cef demo_reflog_branch@{2}: commit (initial): Initial commit

To show the reflog for a git stash, assuming that some changes are already stashed, run the following command:

$ git reflog stash 
1a03d4b stash@{0}: WIP on demo_reflog_branch: a4d1cef git reflog more content

The displayed ref pointers of the git reflog command can be passed to other Git commands like git diff as follows:

$ git diff stash@{0} demo_reflog_branch@{0}

The command above will display Git diff output comparing the stash@{0} changes against the demo_reflog_branch@{0} ref.


Timed Reflogs

Every reflog record has a corresponding timestamp associated with it. These timestamps can be leveraged as a qualifier, which is a token of Git ref pointer syntax. This permits to filter Git reflogs by time. Here are some examples of available time qualifiers:

  • 1.minute.ago
  • 1.hour.ago
  • 1.day.ago
  • yesterday
  • 1.week.ago
  • 1.month.ago
  • 1.year.ago
  • 2016-06-23.10:25:00

Time qualifiers can be used as a combination (e.g. 1.month.ago.2.hours.ago), or as plural forms (e.g. 3.weeks.ago).

Time qualifiers can be given to other git commands.

$ git diff master@{0} master@{1.month.ago}

The command above display a diff between the current master branch and the master 1 month ago.


Subcommands of Git Reflog

Some additional arguments of the git reflog command are considered to be subcommands. These subcommands are presented as follows:

Show - git reflog show subcommand

The show is the default option. For example, the following command:

$ git reflog maste@{0}

is similar to the command:

$ git reflog show master@{0}

The git reflog show command is an alias for the git log -g --abbrev-commit --pretty=oneline command.

Expire - git reflog expire subcommand

The git reflog expire subcommand is used for removing old or unattainable reflog entries. This command may cause data loss. Git uses the expire subcommand internally to change the expiration date of reflog entries. Adding a -n or --dry-run to the git reflog expire command will execute a "dry run" that output which reflog entries are marked to be pruned without pruning them.

By default, the reflog expiration date is set to 90 days. To change the expiration time, we can pass a command-line argument --expire=time to the git reflog expire command or set a git configuration name of gc.reflogExpire.

Delete - git reflog delete subcommand

The git reflog delete subcommand is used for deleting passed reflog entries. The git reflog delete may cause data loss as git reflog expire, so caution should be taken when utilizing the delete option.


Recovering Lost Commits

Git never loses commits, even during history rewriting operations like rebasing or commit amending. For our example, we have made some new changes to our repository.

The output of the git log --pretty=online command looks like the following:

$ git log --pretty=oneline
92b836f1a893d0ef628d1d6628ac9887655c7d08 migrating content
128be37f7bf911163de43239338479d1d66bd53f adding content
eed1cef01bdc42c4cbd0058a94e4cf80671513eb initial commit

Now we add some new changes to the repository and run the following:

# make changes to HEAD 
$ git commit -am "DAO changes"

After the above command, the log will look like this:

$ git log --pretty=oneline
1a03d4bb1604fd7958d328909faafd90347403cf DAO changes
92b836f1a893d0ef628d1d6628ac9887655c7d08 migrating content
128be37f7bf911163de43239338479d1d66bd53f adding content
eed1cef01bdc42c4cbd0058a94e4cf80671513eb initial commit

At this stage, we perform an interactive rebase against the master by running the following command:

$ git rebase -i origin\master

Through the rebase, we mark some commits for squash using the s rebase subcommand. In our example, we will squash a few commits into the most recent "DAO changes".

After the squash, the git log --pretty=oneliney command will look like:

1a03d4bb1604fd7958d328909faafd90347403mp API changes eed1cef01bdc42c4cbd0058a94e4cf80671513eb initial commit

Now commits that are marked for squashing are no longer there. If we need to work on a squashed commit, we can use the reflog command.

1a03d4b HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog
c6db2c8 HEAD@{1}: rebase -i (start): checkout origin/master
90bb007 HEAD@{2}: commit: DAO changes

The above output shows reflog entries for the start and finish of the rebase, and before that is the "DAO changes" commit. The reflog ref can be passed to the git reset command to recover a commit before the rebase.

$ git reset HEAD@{2}

The command above will move HEAD to point to the commit "DAO changes", and at the same time, restore the other squashed commits.



ExpectoCode is optimized for learning. Tutorials and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using this site, you agree to have read and accepted our terms of use, cookie and privacy policy.
Copyright 2020-2021 by ExpectoCode. All Rights Reserved.