Speeding up magit - Jake McCrary
-->
-->
-->
Speeding up magit
Published on<br>November 14, 2020
Magit is a great Emacs tool and by far my favorite way of interacting with git repositories. I use Magit nearly every day.<br>Unfortunately, refreshing the magit-status buffer is sluggish when you are working in a large repository.<br>A few months ago, I became sick of waiting and investigated how to speed up refreshing the status buffer. After doing some research, I learned about the magit-refresh-verbose variable.<br>Setting magit-refresh-verbose to true causes Magit to print some very useful output to your *Messages* buffer. This output shows how many seconds each step of magit-status takes.<br>Here is the output for the large repo that caused me to look into this.<br>Refreshing buffer ‘magit: example-repo’...<br>magit-insert-error-header 1e-06<br>magit-insert-diff-filter-header 2.3e-05<br>magit-insert-head-branch-header 0.026227<br>magit-insert-upstream-branch-header 0.014285<br>magit-insert-push-branch-header 0.005662<br>magit-insert-tags-header 1.7119309999999999<br>magit-insert-status-headers 1.767466<br>magit-insert-merge-log 0.005947<br>magit-insert-rebase-sequence 0.000115<br>magit-insert-am-sequence 5.1e-05<br>magit-insert-sequencer-sequence 0.000105<br>magit-insert-bisect-output 5.3e-05<br>magit-insert-bisect-rest 1.1e-05<br>magit-insert-bisect-log 1e-05<br>magit-insert-untracked-files 0.259485<br>magit-insert-unstaged-changes 0.031528<br>magit-insert-staged-changes 0.017763<br>magit-insert-stashes 0.028514<br>magit-insert-unpushed-to-pushremote 0.911193<br>magit-insert-unpushed-to-upstream-or-recent 0.497709<br>magit-insert-unpulled-from-pushremote 7.2e-05<br>magit-insert-unpulled-from-upstream 0.446168<br>Refreshing buffer ‘magit: example-repo’...done (4.003s)<br>The total time is found in the last line and we can see it took four seconds. Four seconds is an incredibly long time to wait before interacting with Magit.<br>You can change how much work Magit does by removing functions from the magit-status-sections-hook with remove-hook. I looked at the timings and and tried removing anything I decided was slow and something I didn't think I'd miss. For me, that list includes magit-insert-tags-header, magit-insert-status-headers, magit-insert-unpushed-to-pushremote, magit-insert-unpushed-to-upstream-or-recent, and magit-insert-unpulled-from-upstream. I also removed magit-insert-unpulled-from-pushremote.<br>You remove a function from a hook by adding elisp similar to (remove-hook 'magit-status-sections-hook 'magit-insert-tags-header) to your Emacs configuration.<br>I use use-package to configure mine and below is what my magit section looks like.<br>Lines 20-25 remove the hooks. I also hard-code magit-git-executable to be the full path of the git executable on line 5 because folks said this made a difference on macOS.<br>(use-package magit<br>:ensure t<br>:bind ("C-c g" . magit-status)<br>:custom<br>(magit-git-executable "/usr/local/bin/git")<br>:init<br>(use-package with-editor :ensure t)
;; Have magit-status go full screen and quit to previous<br>;; configuration. Taken from<br>;; http://whattheemacsd.com/setup-magit.el-01.html#comment-748135498<br>;; and http://irreal.org/blog/?p=2253<br>(defadvice magit-status (around magit-fullscreen activate)<br>(window-configuration-to-register :magit-fullscreen)<br>ad-do-it<br>(delete-other-windows))<br>(defadvice magit-quit-window (after magit-restore-screen activate)<br>(jump-to-register :magit-fullscreen))<br>:config<br>(remove-hook 'magit-status-sections-hook 'magit-insert-tags-header)<br>(remove-hook 'magit-status-sections-hook 'magit-insert-status-headers)<br>(remove-hook 'magit-status-sections-hook 'magit-insert-unpushed-to-pushremote)<br>(remove-hook 'magit-status-sections-hook 'magit-insert-unpulled-from-pushremote)<br>(remove-hook 'magit-status-sections-hook 'magit-insert-unpulled-from-upstream)<br>(remove-hook 'magit-status-sections-hook 'magit-insert-unpushed-to-upstream-or-recent))<br>After this change, my magit-status buffer refreshes in under half a second.<br>Refreshing buffer ‘magit: example-repo’...<br>magit-insert-merge-log 0.005771<br>magit-insert-rebase-sequence 0.000118<br>magit-insert-am-sequence 5.3e-05<br>magit-insert-sequencer-sequence 0.0001<br>magit-insert-bisect-output 5.5e-05<br>magit-insert-bisect-rest 1.1e-05<br>magit-insert-bisect-log 1.1e-05<br>magit-insert-untracked-files 0.247723<br>magit-insert-unstaged-changes 0.024989<br>magit-insert-staged-changes 0.018397<br>magit-insert-stashes 0.026055<br>Refreshing buffer ‘magit: example-repo’...done (0.348s)<br>What did I lose from the magit-status buffer as a result of these changes? Here is screenshot of the original buffer.
And here is the buffer after.
The difference is drastic1. And so is the speed difference.<br>The increased speed is worth losing the additional information. I interact with git very often and much prefer using Magit to do so. Before these changes, I found myself regressing to using git at the command line and I don't find that to be nearly as enjoyable. Since I've made these changes, I'm back to doing 99% of my git interactions through Magit.<br>Don't settle for slow...