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.
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 🙂
2 thoughts on “Why emacs doesn’t let me do `git rebase -i`…?”
Wow, I also missed that text at the bottom. This magit is quite useful.
Wow I also missed the text at the bottom.