Skip to content

reflog: add --operations and --historical-branch - #2448

Open
HaraldNordgren wants to merge 3 commits into
git:masterfrom
HaraldNordgren:reflog-operations
Open

HaraldNordgren wants to merge 3 commits into
git:masterfrom
HaraldNordgren:reflog-operations

Conversation

@HaraldNordgren

@HaraldNordgren HaraldNordgren commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Create a better reflog. Follows the discussion in https://lore.kernel.org/git/akZfm-igZKeHaDST@pks.im/.

"git reflog" lists every step of a rebase and every branch switch, which makes it hard to see what was done and on which branch. This adds two options to "git reflog" and "git log -g":

  • --operations shows one entry per command, folding a rebase into the entry that finished or aborted it, and leaves out entries that change no branch.
  • --historical-branch decorates each entry with the branch HEAD was on when it was recorded.

Changes in v2:

  • Improve commit messages.

cc: "Kristoffer Haugsbakk" kristofferhaugsbakk@fastmail.com
cc: "D. Ben Knoble" ben.knoble@gmail.com

@HaraldNordgren

Copy link
Copy Markdown
Contributor Author

/submit

@gitgitgadget-git

Copy link
Copy Markdown

Submitted as pull.2448.git.git.1792070038.gitgitgadget@gmail.com

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-git-2448/HaraldNordgren/reflog-operations-v1

To fetch this version to local tag pr-git-2448/HaraldNordgren/reflog-operations-v1:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-git-2448/HaraldNordgren/reflog-operations-v1

@HaraldNordgren
HaraldNordgren force-pushed the reflog-operations branch 2 times, most recently from cca2274 to 4bb992c Compare October 15, 2026 15:39
Comment thread builtin/branch.c
@@ -13,6 +13,7 @@
#include "editor.h"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Kristoffer Haugsbakk" wrote on the Git mailing list (how to reply to this email):

On Thu, Oct 15, 2026, at 15:13, Harald Nordgren via GitGitGadget wrote:
> From: Harald Nordgren <haraldnordgren@gmail.com>
>
> "git checkout" records a move of HEAD in the reflog as "checkout:
> moving from <old> to <new>", "git branch -m" records a rename of the
> current branch as "Branch: renamed <old> to <new>", and "git rebase"
> marks where it starts and ends with steps like "rebase (start)" and
> "rebase (finish)". "@{-<n>}" and "git status" read the switch message
> back, each with its own copy of the prefix,

Here it feels like we are thrown into an enumeration without knowing
what for. What is the problem to solve?

> and a later commit adds a
> reader for all of them.

This clause at the end of the six-line sentence seems to reveal why: we
are about to use these strings in more than one place, so we want to
introduce constants in order to not duplicate anything (no drifting
apart). But the why here should have been put at the start. And the
phrasing is also so passive that I had to do a double-take as to what
“commit” meant. A commit in the reflog under discussion? Or a commit
that *we*/*I* are about to make?

The context is that you are about to use these prefixes in more than one
place. And the principle you are following is no duplication. Then the
details follow. If the details of exactly what they say is worth stating
in the commit message.

>
> Name these strings in reflog.h and use them where the messages are
> written and read, so they cannot drift apart.
>
> Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
> ---
>[snip]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Harald Nordgren wrote on the Git mailing list (how to reply to this email):

> [snip]
>
> The context is that you are about to use these prefixes in more than one
> place. And the principle you are following is no duplication. Then the
> details follow. If the details of exactly what they say is worth stating
> in the commit message.

Thanks!


Harald

@gitgitgadget-git

Copy link
Copy Markdown

User "Kristoffer Haugsbakk" <kristofferhaugsbakk@fastmail.com> has been added to the cc: list.

@gitgitgadget-git

Copy link
Copy Markdown

"Kristoffer Haugsbakk" wrote on the Git mailing list (how to reply to this email):

On Thu, Oct 15, 2026, at 15:13, Harald Nordgren via GitGitGadget wrote:
> Create a better reflog. Follows the discussion in
> https://lore.kernel.org/git/akZfm-igZKeHaDST@pks.im/.
>
> "git reflog" lists every step of a rebase and every branch switch, which
> makes it hard to see what was done and on which branch. This adds two
> options to "git reflog" and "git log -g":
>
>  * --operations shows one entry per command, folding a rebase into the entry
>    that finished or aborted it, and leaves out entries that change no
>    branch.
>  * --historical-branch decorates each entry with the branch HEAD was on when
>    it was recorded.

This sounds very useful. That you rebase many commits and then the reset
points (where each one started and ended) get obscured in the reflog is
classic for me. And I think many have had the same issue. This is why I
sometimes use `ORIG_HEAD` instead, or maybe make a backup ref.

@gitgitgadget-git

Copy link
Copy Markdown

Harald Nordgren wrote on the Git mailing list (how to reply to this email):

> This sounds very useful. That you rebase many commits and then the reset
> points (where each one started and ended) get obscured in the reflog is
> classic for me. And I think many have had the same issue. This is why I
> sometimes use `ORIG_HEAD` instead, or maybe make a backup ref.

Yes! I love the reflog. But I'm also endlessly confused by it.

Sometimes I'll just pick all the commits one by one and do 'git show'
on them to figure out which one to actually pick. Not a great
experience.


Harald

@gitgitgadget-git

Copy link
Copy Markdown

"Kristoffer Haugsbakk" wrote on the Git mailing list (how to reply to this email):

On Thu, Oct 15, 2026, at 17:24, Harald Nordgren wrote:
>> This sounds very useful. That you rebase many commits and then the reset
>> points (where each one started and ended) get obscured in the reflog is
>> classic for me. And I think many have had the same issue. This is why I
>> sometimes use `ORIG_HEAD` instead, or maybe make a backup ref.
>
> Yes! I love the reflog. But I'm also endlessly confused by it.
>
> Sometimes I'll just pick all the commits one by one and do 'git show'
> on them to figure out which one to actually pick. Not a great
> experience.

:)

I got a bit curious about this forced workflow now. I tried the first
terminal navigate-and-click Git tool I could think of, tig(1), and it
turns out that you can do this:

    $ tig reflog
    $ # navigate up/down j/k
    $ # See the commit message and diff with `d`

@gitgitgadget-git

Copy link
Copy Markdown

Harald Nordgren wrote on the Git mailing list (how to reply to this email):

> > Sometimes I'll just pick all the commits one by one and do 'git show'
> > on them to figure out which one to actually pick. Not a great
> > experience.
>
> :)
>
> I got a bit curious about this forced workflow now. I tried the first
> terminal navigate-and-click Git tool I could think of, tig(1), and it
> turns out that you can do this:
>
>     $ tig reflog
>     $ # navigate up/down j/k
>     $ # See the commit message and diff with `d`

I don't use tig, lazygit, github desktop or vscode’s version control
extension, not because they’re not good (they probably are) but only
because I don't want to be removed from the fundamentals. I want to
feel the pain of using git :)

But that seems like an improvement, yes, thanks for pointing it out!
Good news is that git options are passed through to tig, so with this
new feature we could run:

    tig reflog --operations


Harald

@gitgitgadget-git

Copy link
Copy Markdown

"D. Ben Knoble" wrote on the Git mailing list (how to reply to this email):

On Thu, Oct 15, 2026 at 12:04 PM Harald Nordgren
<haraldnordgren@gmail.com> wrote:
>
> > This sounds very useful. That you rebase many commits and then the reset
> > points (where each one started and ended) get obscured in the reflog is
> > classic for me. And I think many have had the same issue. This is why I
> > sometimes use `ORIG_HEAD` instead, or maybe make a backup ref.
>
> Yes! I love the reflog. But I'm also endlessly confused by it.
>
> Sometimes I'll just pick all the commits one by one and do 'git show'
> on them to figure out which one to actually pick. Not a great
> experience.

Perhaps `git log -g -p` in that case? :)

-- 
D. Ben Knoble

@gitgitgadget-git

Copy link
Copy Markdown

User "D. Ben Knoble" <ben.knoble@gmail.com> has been added to the cc: list.

@gitgitgadget-git

Copy link
Copy Markdown

"D. Ben Knoble" wrote on the Git mailing list (how to reply to this email):

[Apologies for replying in the wrong chain; it appears I haven't
received 3/3 yet and it's easier for me to reply to a message I have
than one I can only see in lore.]

On Thu, Oct 15, 2026 at 9:20 AM Harald Nordgren via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>   reflog: add --historical-branch to name the branch of each entry

> Teach "git reflog" and "git log -g" a "--historical-branch" option
> that decorates each entry with the branch it was made on, in place of
> the refs that point at the commit now. The name is colored like a
> branch decoration:
>
>   $ git reflog --historical-branch
>   4e5f6a7 (topic) HEAD@{0}: commit: add tests
>   1a2b3c4 (topic) HEAD@{1}: checkout: moving from main to topic
>   8c9d0e1 (main) HEAD@{2}: commit: fix typo

Notice how the "HEAD@" column is now not aligned? I find it really convient to
have fixed-width data at the front of the line so that I can visually pick out
pieces in columns.

So I'd suggest an alternat end-of-line format:

    $ git reflog --historical-branch
    4e5f6a7 HEAD@{0}: commit: add tests (topic)
    1a2b3c4 HEAD@{1}: checkout: moving from main to topic (topic)
    8c9d0e1 HEAD@{2}: commit: fix typo (main)

That might make picking out the branch name a little harder, so I suppose you
could try right before the messages?

    $ git reflog --historical-branch
    4e5f6a7 HEAD@{0}: (topic) commit: add tests
    1a2b3c4 HEAD@{1}: (topic) checkout: moving from main to topic
    8c9d0e1 HEAD@{2}: (main) commit: fix typo

or (since the "operation" prefixes" are useful)

    $ git reflog --historical-branch
    4e5f6a7 HEAD@{0}: commit: (topic) add tests
    1a2b3c4 HEAD@{1}: checkout: (topic) moving from main to topic
    8c9d0e1 HEAD@{2}: commit: (main) fix typo

? Obviously the misalignment in all the examples (except the EOL format) gets
worse when you have some short and some long branch names.

The next commit adds "git reflog --operations", which finds branch
switches, branch renames and the start and end of a rebase by the
messages they leave in the reflog. The commands that write these
messages spell out the strings by hand, and "@{-<n>}" and "git status"
each keep their own copy of the switch prefix to read it back. Reading
them in one more place would add yet another copy that has to stay in
sync.

Name the strings once in reflog.h and use the names wherever the
messages are written or read: the "checkout: moving from " prefix
written by "git checkout", the "Branch: renamed " prefix written by
"git branch -m", and the "start", "finish" and "abort" steps written
by "git rebase".

No change in behavior.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
After a rebase, "git reflog" shows one entry for every commit the
rebase replayed, plus one for its start and one for its end. Together
with an entry for every branch switch, finding where a branch was
before the rebase means reading past all of them.

Teach "git reflog" and "git log -g" an "--operations" option that
shows each rebase as the single entry that finished or aborted it, and
leaves out entries that change no branch, like branch switches and the
"reset: moving to HEAD" that "git stash" and "git merge --abort" leave
behind:

  $ git reflog --operations
  4e5f6a7 HEAD@{0}: rebase (finish): returning to refs/heads/topic
  8c9d0e1 HEAD@{5}: commit: fix typo
  1a2b3c4 HEAD@{7}: commit: add tests

The HEAD@{<n>} numbers keep their usual values, so the previous entry
on the same branch can be used to undo the rebase:

  $ git reset --hard HEAD@{7}

Commands run while a rebase is stopped, such as an amend after an
"edit", are folded into that rebase, and a "git pull --rebase" is shown
as one entry the same way.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
"git reflog" does not say which branch HEAD was on when an entry was
recorded. After switching between a few branches, telling which
commits and rebases belong to which branch means reading back to the
last "checkout: moving from" entry for each of them. Commit
decorations do not help either, since they only name branches that
still point at that commit, and a rebased or amended commit has none.

Teach "git reflog" and "git log -g" a "--historical-branch" option
that shows the branch each entry was made on before its message, in
place of the refs that point at the commit now. The hashes and
selectors stay lined up in their columns, and the name is colored like
a branch decoration:

  $ git reflog --historical-branch
  4e5f6a7 HEAD@{0}: (topic) commit: add tests
  1a2b3c4 HEAD@{1}: (topic) checkout: moving from main to topic
  8c9d0e1 HEAD@{2}: (main) commit: fix typo

Every entry gets a name, including ones whose commits are no longer on
any branch. Entries from before a branch was renamed show its old name,
and entries made on a detached HEAD show "detached at <commit>".
Combined with "--operations", which leaves out the branch switches
themselves, it lists what was done to each branch.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
@gitgitgadget-git

Copy link
Copy Markdown

Harald Nordgren wrote on the Git mailing list (how to reply to this email):

>     $ git reflog --historical-branch
>     4e5f6a7 HEAD@{0}: (topic) commit: add tests
>     1a2b3c4 HEAD@{1}: (topic) checkout: moving from main to topic
>     8c9d0e1 HEAD@{2}: (main) commit: fix typo

Thanks!

This is my favorite then.


Harald

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant