I’m an active user of Magit for all my Git needs within Emacs. One thing I’ve always found missing was nice support for ‘git blame’ — and by ‘nice’ I mean some more comfort than the simple display of its output.
When I’m hunting bugs one thing I often need is not only the information who modified a certain line but also who modified the line before that. Also what I’d like is having both the source code (including syntax highlighting, of course) and the blame information shown side-by-side with quick access to the log message for particular commits.
That’s what ‘mo-git-blame’ tries to solve. It is a standalone mode that can be used with any of the various Git version control modes. Here are a couple of its features:
- Shows the output of ‘git blame’ and the file content side-by-side with syntax highlighting for the content
- Show the log messages for the current revision or the revision in the current line
- Show the diff (via ‘git show’) for the current revision or the revision in the current line
- Show the file content for the revision in the current line
- Call ‘git blame’ for the same file for the revision in the current line
Here’s what it looks like:
You can download the sources from my Git repository or directly with
git clone git://github.com/mbunkus/mo-git-blame.git
Installation and usage instructions are included both in the file itself and its README, but here’s the short version:
(add-to-list 'load-path "~/.emacs.d/mo-git-blame")
(autoload 'mo-git-blame-file "mo-git-blame" nil t)
(autoload 'mo-git-blame-current "mo-git-blame" nil t)
Great job. Uploaded this to github (http://github.com/voins/mo-git-blame). There will be patches. :)
How does this differ from vc-annotate (which does support git in recent emacs versions)?
So then… could this be integrated into Magit?
As magit doesn’t have a full-blown file manager (meaning it only shows modified files) such an integration would be limited to the files it actually lists as modified. That isn’t hard to do; basically a function that checks whether or not point is at a file and use that file’s name for mo-git-blame. I’ll try to write that up next week.
Or did you have something else in mind?
To be honest, I doubt it. It doesn’t quite fit. I’d be happy to stick a recommendation for it in the manual though.
That’s what I thought as well and why I didn’t try to integrate it before — even with such a simple method as I outlined in the comment above.
Opps, I mean to reply to the other philip. I don’t know computers very well…
This looks great.
But is it possible that it does not cope with hard symlinks? Because of several reasons we have to link to our git repo this way (chroot). Then when I try mo-git-blame-current the following error is shown:
fatal: Not a valid object name d7912b8:../../../../../home/nick/src/modules/Affiliate/Actions/CRUD.pm
But Magit itself shows no problems.
Not workin’ for me on MacOSX with Emacs 23.2; it hangs emacs waiting for the git blame command to finish, and if I kill the git command Emacs remains hung so I have to kill it too. Interestingly, the git command it hangs on works just fine from the command-line!
I noticed the same thing. I’m just going to use vc-annotate for the short term I guess.
The MacOSX problems are fixed, but frankly I’m a little perplexed as to how to use this. I ran it, and I wanted to find out who (and which commit) was responsible for a given line of source, but I didn’t see a way to do that. What am I missing?
First, visit the file you want to blame. Then execute `mo-git-blame-current’. This works best if you have only one window shown.
MGB will split that window into two: the left one will show the output of “git blame –interactive”, the right one will contain the file content at the revision you’re blaming for. Initially this is the same revision your HEAD is at, but you can re-blame for other revisions by pressing some of the keys listed in the help for `mo-git-blame-current’ (or the mode’s key map).
Whenever you scroll either of the two windows the other will be scrolled by the same amount.
Is this enough to get you started?
Well, it’s still not working for me. The latest problem is, when I visit the file and invoke mo-git-blame-current, I get this:
fatal: ‘../../../../../../../Users/dave/src/llvm/tools/clang/lib/Sema/SemaExpr.cpp’ is outside repository.
Oh, weird. There’s a directory symlink in the path to the file **above the repository directory** and that confuses mo-git-blame. If I open it by its canonical name, it works. Maybe you could make mo-git-blame more resilient to this
One further thing: I have diff-mode-read-only set, and once I hit `RET’ in the buffer with the revision numbers, I can’t do it again until I kill the diff buffer.
Hmm, scrolling in the mo-git-blame buffer seems to be indiscriminately scrolling whatever buffer happens to be in the other window. Should I start posting issues at https://github.com/mbunkus/mo-git-blame/issues ?
Yes, please. I might forget about otherwise; too many things to do at the moment. Thanks.