Mitar Mitar - 2 months ago 11
Git Question

What is git reflog identity?


, I see that when using custom formatting for
git log
, there are "reflog identity" values possible. What is a reflog identity?


These refer to reflog entries. A reflog is simply a record of updates to a reference, and a reference itself is simply a generalization of branch and tag names and special names like HEAD.

Reflogs are normally enabled on client repositories (like yours) and normally disabled on server repositories. This is, naturally enough, configurable. The front end command people mostly use for looking at their reflogs is git reflog. You can run that now if you like, but doing so won't help explain %ge and so on. So we'll do something different: Run git log -g.

Running git reflog basically runs git log --oneline -g. By running git log -g yourself, you can leave out the --oneline, and hence see more than one line for each reflog entry.

The output will resemble the following, with names and email addresses changed:

commit 08b876daae9944d1a6fba271cfcd9629c13dfd69
Reflog: HEAD@{0} (A U Thor <>)
Reflog message: commit: initial torturetest code
Author: A U Thor <>
Date:   Sun Aug 7 01:59:31 2016 -0700

    initial torturetest code

commit 8bb118938b5c6a2978f13e74525b594a48226571
Reflog: HEAD@{1} (A U Thor <>)
Reflog message: checkout: moving from master to torturetest
Author: Someone Else <>
Date:   Sat Jul 16 02:00:46 2016 +0200

    Allow backend ...

The most recent commit is one I made last night (well, this morning). This is HEAD@{0}. It represents some commit (whose true name is the big ugly SHA-1 hash starting with 08b87...). The commit itself has an author (me, though I changed the name here for display purposes), date, commit message, and so on—but the reflog entry, HEAD@{0}, also has an author (me again), date, and message.

In this case, the commit's author and the reflog author are the same. Even the reflog message is basically the same as the commit subject (the Reflog message: line just as the word commit: inserted). So that's not much help—but take a look at the very next example, commit 8bb11....

This reflog entry has me as the reflog author, and someone else as the commit author.1 Moreover, the reflog message, checkout: moving from master to torturetest, is completely unrelated to the commit's subject line, which begins with Allow backend.

If you compare this to the short output from git log -g --oneline or git reflog—both of these examine the reflog for HEAD—you'll see only the reflog message, along with the commit ID and the reflog selector.

One other thing is worth noting here. In regular git log output, each commit normally2 appears only once. In git log -g output, however, a commit can appear repeatedly, because Git is looking at the hash IDs stored in the reflog itself. If you switch back and forth between branches that point to the same commit, or use git reset to change a branch to point back to a commit it pointed-to earlier, or run git rebase, or do any number of similar things, you can easily get a reference—this applies to both HEAD and branch names—that points to the same commit in multiple different reflog entries.

In my case, for instance, I apparently vacillated a bit on the name torturetest or something:

08b876d HEAD@{0}: commit: initial torturetest code
8bb1189 HEAD@{1}: checkout: moving from master to torturetest
8bb1189 HEAD@{2}: checkout: moving from torturetest to master

(I'm not really sure what this was about—perhaps just running too many Git commands without remembering which repository I was in. :-) )

Returning directly to your question:

What is a reflog identity?

These are the names and email addresses stored in each reflog entry. In the case of a private Git repository, on your own client, these are likely to all be the same all the time. But since you can run git config --global "New User Name" and git config --global new@address any time to change them,3 they could vary.

1That someone else is also the committer, if you get to wondering. The commit's author and committer, and their corresponding dates and email addresses, are stored in the commit itself. The reflog author, date, and email address are stored in the reflog entry. It's actually a plain text file today, so you can just look at .git/logs/HEAD and .git/logs/refs/heads/master to see the raw reflog data. The format is not particularly well documented, but is pretty obvious: it has the old and new values for the reference; the reflog's author, email, and date-stamp information; and the reflog message.

2The exception here, beside the one for reflogs themselves of course, occurs when using git log -m -p to split merge commits. Normally git log skips merge commits entirely, while git show shows combined diffs for them. (The documentation on combined diffs is somewhat buried—search here on StackOverflow for the term "combined diffs".)

If you convince git log to show a diff, it too can show a combined diff. In all cases, combined diffs may omit crucial information, so you can tell these commands to do something different: for each parent of a merge, produce a diff of the merge commit's tree against that particular parent's tree. This is what the -m flag does.

When showing a diff of commit merge commit 1234567... against parent #1, Git shows you the merge commit information, then the diff. Then, when showing a diff of merge commit 1234567... against parent #2, Git shows you the merge commit information again, before the second diff. So this is how git log can show the same commit more than once.

3You can also use git -c and git -c, or in this particular case, special Git environment variables. Using git -c is especially convenient for one-off tests, as in the answer I wrote recently about Git diff color options.