Why emacs doesn’t let me do `git rebase -i`…?

Backstory

Yesterday, I needed to do an interactive git rebase. When you do git rebase -i, your editor opens a file named “.git/rebase-merge/git-rebase-todo” and you need to edit the file in order to choose which commits you want to keep, which commits you want to squash… etc. In my case, emacs opened the file, but I was unable to edit the file. I spent an hour of mine to figure out why I am unable to do rebase in emacs.

Debugging

I tried editing the file, but failed because the buffer was read only. Here are the things I checked:

  • Permissions of the file .git/rebase-merge/git-rebase-todo in the concerned git repository and I had the read/write permission on that file.
  • Tried to edit the same with other editors and it worked fine.
  • Uninstalled magit and everything worked fine. So, it turned out that magit was somehow preventing me to edit the file.

Magit is the culprit, but why & how?

After knowing that magit is the cause of this weird behavior, I skimmed through magit manual and got to know about git rebase mode. Whenever one tries to do an interactive git rebase from command line, emacs opens .git/rebase-merge/git-rebase-todo in rebase mode and gives the user an easy interface to choose options for rebasing (squash, pick, fixup etc.).

Disabling git rebase mode in magit

I figured out two ways to disable rebase mode, they might be hacky solutions for an emacs nerd, but they worked fine for me (if you have a better solution, then please let me know):

  • I looked into ~/.emacs.d/elpa/magit-2.11.0 directory. I saw git-rebase.el & git-rebase.elc, I deleted both of them, tried doing an interactive rebase and everything worked fine.
  • I commented these lines in ~/emacs.d/elpa/magit-2.11.0/magit-autoloads.el, recompiled it and everything worked fine:
(autoload 'git-rebase-mode "git-rebase" "\
Major mode for editing of a Git rebase file.

Rebase files are generated when you run 'git rebase -i' or run
`magit-interactive-rebase'.  They describe how Git should perform
the rebase.  See the documentation for git-rebase (e.g., by
running 'man git-rebase' at the command line) for details.

\(fn)" t nil)

(defconst git-rebase-filename-regexp "/git-rebase-todo\\'")

(add-to-list 'auto-mode-alist (cons git-rebase-filename-regexp 'git-rebase-mode))

Not disabling rebase mode but using it

Rebase mode pissed me off  because

  • It came as an unwanted surprise to me.
  • I ignored the messages which magit adds because I am too used to do it the usual way.
# Commands:
# C-c C-c tell Git to make it happen
# C-c C-k tell Git that you changed your mind, i.e. abort
# p move point to previous line
# n move point to next line
# M-p move the commit at point up
# M-n move the commit at point down
# SPC show the commit at point in another buffer
# RET show the commit at point in another buffer and select its window
# C-_ undo last change
# k drop the commit at point
# y insert a line for an arbitrary commit
# z add noop action at point
# c pick = use commit
# r, w reword = use commit, but edit the commit message
# e, m edit = use commit, but stop for amending
# s squash = use commit, but meld into previous commit
# f fixup = like "squash", but discard this commit's log message
# x exec = run command (the rest of the line) using shell

But it could be a useful feature for some people. So, you can keep it enabled if you want 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s