At some point I'll write up my full thoughts on switching to macOS full-time as my development environment (and just using that OS/ecosystem in general), but for now, I wanted to make a quick note of one of my larger pain points: git merging and vim 😒
I've been using Visual Studio Code (VSCode) for years now and, for the most part, I think it's the best IDE yet created. It has some flaws, but things basically work, and the plugin store is rich in useful tools and additional functionality. On Windows, one of the things I've found most impressive about the editor is just how well things magically fit together. Most of the tools I want to work with integrate with VSCode seamlessly, and top of that list is Git. Being able to run terminal windows directly within the editor is great, and the native Source Control panel works incredibly well for keeping track of branch changes, merge commits, etc. For the most part, I mainly use VSCode for sanity checking and still interact with Git predominantly via the command line, but that GUI has come in clutch on more than one occasion.
Best of all – particularly as someone who often works in teams with multiple people editing files at once – VSCode has a really seamless method for dealing with merge conflicts. This has gotten even better recently with their revamped diffing GUI, but even before then, I found doing this in VSCode far easier to grok than most environments (including the Git GUI itself). One of my favourite aspects of this has always been that I can jump between CLI and GUI without it mattering:
- Run a merge command and get conflicts;
- Check through the flagged files in the Source Control panel, cutting and pasting away until I have things straightened out in the main editor window;
- Stage everything for in the GUI;
- Hop back to the CLI and run git commit;
- Check the commit message directly in the VSCode editor, hit "save file", close that window, and the commit just magically completes.
It's maybe a slightly opaque user flow, but once you understand the steps, it just works every time.
Or, at least, it works every time on Windows. On Mac, it seemed to be completely broken 😅
How to Exit Vim
I've seen this joke bandied around the web for years and never really paid it much attention. Outside of one previous colleague that occasionally used it, I've never needed to even think about vim. I vaguely understand the appeal, but as someone who broadly prefers GUIs to CLIs, it was never an option I've seriously considered.
What I've never understood is that it just comes preinstalled on macOS 😬 I'd always assumed it was a third-party tool or something, but I now see it's a little more akin to PowerShell on Windows: a supercharged CLI tool that sits on top of the native terminal program. In and of itself, that would be fine, except unlike PowerShell, vim seems to have an annoying habit of being set as the default editor for certain commands or functionality. As far as I can tell, there isn't really any way to determine when a Terminal window becomes a vim window, it just suddenly takes over without any warning or obvious helper options to get you back out. Great user experience there, Apple, thanks 👍
So far, the most egregious place this has happened is with Git, where (for some god-forsaken reason) the default editor is configured as vim. What sadist ever thought this was the most likely user preference is beyond me, but perhaps the Terminal application isn't powerful enough for this kind of text editing 🤷♂️
What this means is that, during a merge conflict resolution, when you get to the stage where it pops up a commit message "window" to confirm/reject, on macOS (even from within VSCode), vim will just take control. This took me several weeks of frustration and occasional web searches to actually work out (again, it's not clear what is vim and what is Terminal, at least not to me), and even once I had, I still had no clear way on how to actually confirm the message and let Git progress. During this time, I reverted to just using the Source Control GUI instead, but this is suboptimal at best.
One of the big issues is that, on most of my repositories, we're running some kind of pre-commit tool, such as Husky. That's fine in most cases, but if they fail outside of a CLI, you're left with no real error messaging or understanding of what's going wrong. And with big merge conflict resolution commits, the chances of a secondary ripple effect borking another piece of code is higher than normal, so Husky kept falling over (correctly).
Eventually, my searches brought up a minor resolution: there is a way to switch the default Git editor from vim to VSCode 🎉 Unfortunately, this has also proven to be a bit trickier than you would first expect 😬
(But before we hop into that, the answer to the title question is: type :qa
and hit Enter into the vim window. Just in case you're also stuck in Git merge hell, looping round-and-round, unsure how to escape 😅. Though this won't actually run the commit, it will give you back your terminal.)
Vanquishing Vim
Right, so how do you actually get back to using a modern and user-friendly Git editor, like VSCode? Well, the first answer I came across claimed that I just needed to add a line to my global Git configuration file (git.config
), a task that is made needlessly annoying on macOS by the lack of a competent file browser. So instead of doing this the logical way (find file; open file; edit file; save file), let's pop open a new terminal window and type in the following:
git config --global core.editor "code --wait $MERGED"
That should successfully update your Git config with the relevant commands, but before you celebrate, it's worth double checking that the code
CLI is actually installed. Type into the same terminal:
code --version
And you should see some useful information, such as the version number (alongside some kind of UUID and, for some reason, the CPU architecture format of the PC you're using 🤷♂️).
Chances are, though, that you won't. You'll just get an error message about an unknown command. If this is what you see, we need to install a new CLI. In my experience, this is a not-particularly fun thing to do on macOS, but luckily Microsoft is just out here, showing us all how to make competent, friendly user experiences (who'd'a thunk that!).
- Open up VSCode;
- Press cmd + shift + p (or use View → Command Palette from the toolbar);
- Type in "install" and select the "Shell Command: Install 'code' command in PATH" option;
- Profit 🤑
Hopefully, you'll see a nice success message, and now retrying the above version command, you see the correct output instead of any error 🎉
Except... that didn't work for me. Instead, I got another error message from VSCode to tell me that I had to "unlink" a specific folder first. Sigh...
Right, the final step is to open up a new terminal again and type in the following:
sudo chown -R {your_username} {filepath}
Replacing the username with your local Mac account name and the file path with whatever location VSCode just complained about needing to unlink – most likely /usr/local/bin
. For example:
sudo chown -R janesmith /user/local/bin
You'll be asked for a password (which should be the password for the account user you've just input), so enter that and then repeat the steps in VSCode above. This time you should (🤞) get a success notification.
At long last, we have vanquished vim and taken back control of our Git file editing 🥳 To confirm this has worked, in your terminal window, execute the following:
git config --global --edit
If all's well then this will pop open your Git config file in VSCode directly, so you never have to mess around with a CLI editor again (well, apart from having to open the file from the CLI in the first place – yay macOS 😅). The fact that something this simple (and automatic on Windows) took me almost two months of frustration and web searching is astonishing to me, but hopefully it actually "just works" for most of you 😉
(PS: if this hasn't solved your issue, I'm extremely sorry. I've linked some of the more useful Stack Overflow threads that I called on in the Resources section below. Best of luck ☘😬)