17

I love undo-tree (screenshot below). It provides an easy way for navigating through different versions of a file (top window) by letting the user move around the file's history tree in a separate window (bottom window) with simple keys such as n, p and C-b and C-f to switch across descendants of the same parent.

Most notably, undo-tree updates the buffer holding the file with the corresponding version based on the selection in the tree view, automatically.

Of course, magit is phenomenal for git, and it would be amazing if it had a similar ability, i.e. letting users navigate a file's git history interactively while simultaneously updating the buffer holding the file automatically.

Is this at all possible with magit today?

enter image description here

3
  • Don't know if it's possible with magit but have a lookt at github.com/pidu/git-timemachine
    – clemera
    Commented Oct 10, 2015 at 20:57
  • I'm not sure, but I think undo-tree uses a tree (it's in the name :-p), whereas Git history is a directed acyclic graph. It might be non-trivial.
    – suvayu
    Commented Oct 12, 2015 at 6:31
  • 2
    Magit does support something like this, but I am currently changing how the feature is turned on. I'll post an answer when I am done with that.
    – tarsius
    Commented Oct 13, 2015 at 0:20

1 Answer 1

8

Magit recently gained support for something like this, but the feature is still a bit rough around the edges and has to be enabled explicitly.


A similar feature has existed for a long time - when you move from one commit to another in a log buffer, and another window in the same frame is the repository's revision buffer, then that buffer is refreshed to show that commit instead of whatever commit it was previously showing.

Until very recently the revision buffer was created when you first moved from one commit to another. I have changed that behavior and now the revision buffer is only ever updated. If no window in the same frame already displays that buffer, then moving around the log will no longer cause the buffer to be displayed in some new window or an existing window which previously displayed some other buffer.

So now you have to press SPC once to display the revision buffer. Only then will it start being updated when you move around the log buffer.

If you don't want the revision buffer to be updated, then do this:

(remove-hook 'magit-section-movement-hook
             'magit-log-maybe-update-revision-buffer)

If on the other hand you also want the revision buffer to be updated when moving around in the status buffer, then use this:

(add-hook 'magit-section-movement-hook
          'magit-status-maybe-update-revision-buffer)

It is now possible for a blob buffer to be automatically updated in a similar way. First add this:

(add-hook 'magit-section-movement-hook
          'magit-log-maybe-update-blob-buffer)

And maybe also:

(add-hook 'magit-section-movement-hook
          'magit-status-maybe-update-blob-buffer)

Then, inside a log (or status) buffer press RET to display or update the revision buffer, and to also switch to that buffer. Move to the file you are interested in and press RET again. You are now in a "blob-visiting" buffer, which is similar to a file-visiting buffer, except that it does not visit the file in the working tree but the file as it was in some commit.

Switch back to the log (or status) buffer and move to another commit. The blob buffer is being updated.


Note that displaying another blob, does not actually reuse the existing blob buffer. Instead it creates a new buffer which visits that blob and then displays that buffer in the window which previously displayed the other blob buffer. That other buffer is not being deleted, which unfortunately means that quite a few buffers can accumulate in a short period of time. Which would be one of those rough edges, I mentioned earlier. Pressing q in a blob buffer does delete it, so you can clean up by going to the window which was used to display the various blob buffers and keep pressing q until all the buffers have been deleted.

Additionally it is possible to navigate to the next or previous blob from within a blob buffer using p and n. I assume that in most cases you start with a recent blob and then move backward to older blobs using p. If you do that and then want to move in the other direction, I recommend you use q to kill the current buffer and thereby move to the previous buffer i.e. the next blob.

Also note that you don't have to first visit a revision to be able to visit a blob. You could also use M-x magit-find-file RET <revision> RET <file> RET directly, but I find that less convenient.

2
  • Thank you tarsius. I am working with magit 20151014.231 (the latest as far as I can tell). I tried following the steps you described above. I went to magit-log-buffer-file which allows me to navigate the commits up and down with n and p but when I press SPC or RET on one of them I get: Symbol's value as variable is void: magit-blame-mode Commented Oct 14, 2015 at 14:35
  • You probably added magit-blame-maybe-update-revision-buffer to magit-section-movement-hook by mistake.
    – tarsius
    Commented Oct 15, 2015 at 6:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.