I am excited to announce the release of Magit version 2.9, consisting of 250 commits since the last feature release 15 weeks ago. The release notes can be found here.
Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains.
For more information about Magit, see https://magit.vc.
Dmitriy from Prospect One created a new magical logo for Magit, inspired by Git’s logo. Thanks a lot!
With its 250 commits, this release is larger than the other feature releases this year. Like mentioned in the announcement of the previous release, we did concentrate on bug fixes and cleaning things up. Additionally many features saw minor improvements that aren’t bug fixes but still aren’t all that noteworthy when looked at in isolation.
This release also contains a number of breaking changes, most of which can be easily reverted.
Please refer to the release notes for the full list of changes, including instructions on how to revert the breaking changes, near the beginning of the file.
Two of the more noticeable changes involve the bindings of the RET
(return
) key in various places. These are both breaking changes.
RET
is supposed to do the same thing everywhere: it should visit the
thing at point by showing extended information about it in another,
dedicated buffer. RET
is Magit’s primary dwim key binding. While
it always “visits something”, what exactly it visits is highly context
sensitive.
Users quickly learn that it is safe to just press RET
in some
unfamiliar context because doing so never has any side-effects.
(At least when RET
isn’t part of a key sequence. Of course
something like M-x magit-branch-delete RET master RET
is a
destructive action. But the difference is obvious.)
Unfortunately, for historic reasons, there was one exception to that
rule. In a references buffer RET
used to check out the reference
at point, potentially even resulting in a detached HEAD. That is
certainly very surprising, very much a side-effect, and due to the
caused confusion possibly dangerous.
This inconsistent behavior has existed until now because the last
time I tried to fix it, that change was met with protests by users
who often use that buffer to check out another branch. And indeed
for that use-case RET
is much more convenient than b b RET
(the
key binding one would have to use in other buffers, and now also in
the references buffer).
Back then I reverted the change but added an option to allow users
to optionally make the behavior consistent. Now, after having
abstained from changing any key bindings for quite some time, I have
decided that it is much more important that RET
is consistent and
absolutely never has any side-effect, than to avoid upsetting any
muscle-memory. Please note that you can trivially revert this
change locally, by adding (setq magit-visit-ref-behavior
'(checkout-any focus-on-ref))
to your init file.
While RET
now behaves consistently across all of Magit, that does
not mean that its behavior cannot be further improved. This release
also comes with a few such changes involving diffs.
When point is on a removed line inside a diff, then RET
now visits
the commit that still had that line, not the commit which removed
it. Considering that point is on a removed line, RET
is supposed
to visit the thing at point, and that it is not possible to visit
something in a place where it no longer exists, I think this makes
a lot of sense. But since Magit did not use to behave that way it
might be surprising at first. You can easily revert this change by
adding (setq magit-diff-visit-previous-blob nil)
to your init
file.
Also note that at least for the time being staged changes are
excluded from this new behavior. When showing a diff with staged
changes, then RET
still always visits the file in the working
tree, not some blob.
By the way, you can always visit the file in the working tree, even
when Magit would normally visit some blob. Just use M-RET
instead
of RET
. In that case Magit may or may not succeed putting point
on exactly the correct line, but its much more likely now that it
does.
There are two more changes involving RET
inside diffs, which are not
breaking changes:
When visiting a file or blob buffer by pressing RET
while point is
inside a diff, then the position this jumps to is now accurate (even
when jumping to the file in the working tree from a diff that wasn’t
about changes in the working tree).
When visiting a file or blob buffer by pressing RET
while point is
inside a diff, then the buffer may be widened but only if necessary.
If it isn’t necessary to widen the buffer to jump to the appropriate
location, because that position falls into the narrowed region, then
the buffer isn’t widened.
If you have embraced the push-remote, then it probably bothers you
that creating a new local branch from a remote feature branch always
sets that remote branch as the upstream, because in a triangular
work-flow that branch is already the push-branch and the upstream
should be something like master
or origin/master
. Using the new
option magit-branch-adjust-remote-upstream-alist
, you can now tell
Magit’s branching commands to automatically set the upstream to what
you would otherwise configure manually.
Hunk refinement is faster now. Possibly even fast enough for you to
(setq magit-diff-refine-hunk 'all)
to refine all hunks instead of
just the selected one.
The cache that is used to limit the number of calls to git
during
a refresh was improved, so that git config
only has to be called
once (with the --list
argument). That should improve performance
significantly on Windows.
Comments on Reddit.