Is there anything wrong with opening up a new vim tab (for scratch work) while authoring a git commit?

Update: This Seems to Be a Quirk With Vi vs. Vim

On further inspection prompted by @muru's comment, it seems there are a couple of subtleties here.

  1. The EDITOR environment variable was actually unset, so it defaulted to vi instead of vim as originally posted. Edited.
  2. In order for vi to exit with error, it is actually important to attempt to quit first with :q before using :q!, and this behavior can be reproduced without using tabs:

    1. Launch vi:
      vi; echo $?

    2. Type something in insert mode

    3. Attempt to quit with :q and get the error E37: No write since last change (add ! to override)
    4. Actually quit with :q!
    5. Observe that the exit code is 1
  3. Oddly enough, modifying the above steps by (1) using vim instead of vi, or (2) using vi but quitting with :q! directly without using :q first, yields a 0 exit code instead. Both vi and vim have the same exact :version string on my system, so this is probably a difference in how vim behaves when started as vi on the command-line.

Original Steps with Git + Vi

Steps to reproduce:

  1. Start making a new commit:

    $ export EDITOR=vi  # goes without saying :)
    $ git commit
  2. Open up a new tab with :tabe and type something. Anything.

  3. Switch back to the commit tab with gt.
  4. Type some message, and close the commit tab with :x (writing changes).
  5. Now, attempt to quit the tab with :q.
  6. Now, quit the scratch tab with :q! (discarding changes).
  7. Recoil as vi tells you your meticulously-crafted commit message has also been discarded: 😱

    error: There was a problem with the editor 'vi'.
    Please supply the message using either -m or -F option.

What is Git not happy with in this seemingly innocuous series of steps? 🤔

(This gets confusing because I'm testing Vim's behavior, not Vi's)

Vim's exit code indicates success when repeating the above instructions, so it's not clear why Git thinks Vim quit in error:

$ vim a-file; echo "exit code: $?"
exit code: 0

^ This example is identical to how Git launches Vim, given its process entry in that state:

/usr/bin/vi /path/to/git/repo/.git/COMMIT_EDITMSG

Also, swapping the tab exit order by closing the scratch tab first, then the commit tab, has exactly the same result.

Coming back to the million-dollar question—why is this happening? Answers in the form of snarky references to the Vim/Git docs are most welcome 😄

System: macOS High Sierra 10.13.4
vim :version: VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Nov 29 2017 18:37:46)
git --version: git version 2.15.1 (Apple Git-101)

  • when you are inside vim during these steps, are you sure :version actually shows 8.0.1283? – Mass Jun 2 '18 at 21:57
  • Good question @Mass, yes it does. I pulled the vim version text from the blank page at first, and edited the port with the output of :version. It is the same when vim is invoked from git, and directly. – mxxk Jun 3 '18 at 0:17
  • Why is git talking about vi when vim is the editor? Do you have other configuration overriding the EDITOR variable? Maybe $VISUAL, or some git config settings? – muru Jun 4 '18 at 8:02
  • Thanks a lot @muru, you've pointed out what was causing the difference in observed behavior. I went back to check and found out that Vim behaves differently from Vi specifically with its exit code, and that to reproduce it you need to try :q before :q! – mxxk Jun 4 '18 at 17:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.