Just Enough Vim to Rebase at the Speed of Light

Jack Harvey
ClearScore
Published in
7 min readOct 8, 2020

Vim has developed a mythos around it, which reinforces the misconception that it is prohibitively complex. A typical place where people lose out due to this impression is when they begin a Git rebase, and in response to being put into vim, they either: use it suboptimally; abandon vim quickly and force their terminal to use alternative editors; or move completely to a GUI for Git. The problem with this is that configuring your teminal to open external editors is often slow and clunky, and GUIs abstract away the concepts of Git, robbing you of the power and versatility it can offer.

With just a short explanation of the basics, a handful of commands, and a little muscle memory you will be rebasing at a blinding speed.

Basics

Vim has three modes that you need to know about for the purposes of rebasing:

  • NORMAL mode is the mode where you should spend most of your time, using commands to move swiftly around the document.
  • COMMAND mode is for executing commands, obviously, however these commands are distinct from the ones used to navigate documents. In this mode we can execute commands to save the document, close the editor, open new tabs, etc.
  • INSERT mode behaves very much like your typical WYSIWYG editor, less a mouse pointer, so if you've been just getting by with vim then this is probably the mode that you go straight into, but best practice is to only be in this mode when you're entering text.

You move from any mode to NORMAL mode by pressing Esc, you move to INSERT mode by pressing i in NORMAL mode, and you move to COMMAND mode by pressing : in NORMAL mode.

Commands in NORMAL are made up of single keypresses which together describe a complex operation. You will see these commands written out as ce or dgg, i.e. a keypress of c followed by a keypress of e in the first instance, and a v followed by a double press of g in the second. These operations are near infinitely interchangeable, resulting in a vast suite of possible commands. As a basic example, using just what we have already covered, we can create de: "delete; until the end of the current word"

Commands in COMMAND mode are prefixed with a :, for example :vsp.

Motions

There are three primary motion keys: b, e and w.

The motion described by b is: "to the beginning of the current word"

The movement described by e is: "to the end of the next word"

The movement described by w is: "to the beginning of the next word"

Interacting with text

When in NORMAL mode, the d key performs text deletions, and is paired either with the aforementioned motions or with another press of d, resulting in dd and deleting the entire line.

Often when deleting text you want to begin entering some new text straight away. This is where c comes in handy. It performs delete in the same manner as d, but will put you into INSERT mode immediately without any further input.

In both cases this deleted text is placed into the register, a kind of clipboard, and will be instantly available to paste. You can paste text by pressing p.

hjkl

One goal of vim is to enable you to work without moving your hands away from the home row, in order to be as quick and efficient as possible. As a result using the arrow keys is strongly discouraged, instead h, j, k, & l are to be used instead of left, down, up, right respectively—essentially the arrow keys flattened out.

Miscellaneous commands

We all make mistakes, so u is used for undo. Conversely CTRL + r is used for redo.

When you’re finished editing your file, press Esc to enter NORMAL mode, and then press : to enter COMMAND mode. Now you can press wq, which should result in :wq displaying at the bottom of your terminal screen.

Now press enter and you will write your file to disk and quit vim.

As you may have picked up, you can also write without exiting by performing :w, and quit without saving by performing :q. If you have modified the file, vim will prevent you from exiting without saving, but you can force exit with :q!.

Cheatsheet

That was a lot of commands! They’re probably quite hard to remember when presented in sentences, so here is a handy and easily bookmarked reference which contains all the commands we’ve covered.

Setup

A big hurdle that makes vim inaccessible is that it comes with almost no defaults whatsoever, so we’re going to do a bit of basic setup in order to give you some creature comforts. Vim pulls all of its configuration from a vimrc file. The first place vim looks for this file is home, so that's where we're going to store our's. For Mac users this file is located at ~/.vimrc, for Windows users it is often located at Users/<Name>/vimrc, you can confirm the directory by executing :echo $VIM in vim.

The following configuration will provide an indication of the current mode (INSERT, NORMAL, COMMAND) and whether or not the current file has been modified relative to what is saved on disk.

So, let’s create a .vimrc using vim (hah). Execute $ vim <vim_path> in your terminal. Unfortunately by default vim's registers are not the same as the system clipboard (if you would like it to do so you can find instructions on Google). So once you have copied the text below, you will need to press CMD + v or CTRL + v in order to paste it.

set laststatus=2
set statusline=
set statusline+=%{StatuslineMode()}
set statusline+=%=
set statusline+=%m
function! StatuslineMode()
let l:mode=mode()
if l:mode==#"n"
return "NORMAL"
elseif l:mode==?"v"
return "VISUAL"
elseif l:mode==#"i"
return "INSERT"
elseif l:mode==#"R"
return "REPLACE"
elseif l:mode==?"s"
return "SELECT"
elseif l:mode==#"t"
return "TERMINAL"
elseif l:mode==#"c"
return "COMMAND"
elseif l:mode==#"!"
return "SHELL"
endif
endfunction

I hate just giving out a blob of config, so let’s step through line by line.

set laststatus=2

Set the statusline to always display

set statusline=
set statusline+=%{StatuslineMode()}

Reset the statusline to blank, and then append the result of the function that we will define in a moment.

set statusline+=%=
set statusline+=%m

Append a special character to right align all following characters, and then append the modified flag. This will let us know whether or not the current document has been saved to disk or not.

function! StatuslineMode()
let l:mode=mode()

Define a function called StatuslineMode, and assign the current mode to the variable l:mode.

if l:mode==#"n"
return "NORMAL"

endif

mode() that is assigned to our l:mode variable only returns a single character, which isn't particularly human-readable, so we take that single character and return the appropriate long form name. In the snippet above we see that n maps to NORMAL.

Once you’ve completed that successfully, your vim should look like below.

You can keep adding to your configuration if you like, this is just intended to get you started!

Putting It All Together

In the following clip we will fixup one commit into it’s predecessor, and then delete the subsequent commit as we no longer need it. Then we will save the file and exit to complete the rebase.

Here we move to the commit we wish to modify, and then we leverage ce to change the word pick, and so we enter f, then return to NORMAL mode. Then we move down to the next commit and press dd in order to delete the line, effectively dropping the commit. We return to NORMAL mode again and then enter :wq in order to save the changes and quit. Then our rebase is complete.

Further reading

If you want to learn more about vim, here are some resources to get you started:

https://vim-adventures.com/ — A good game for getting muscle memory, however will eventually ask you to pay. The free portion is worthwhile though.

http://www.vimgenius.com/lessons/vim-intro

http://vimcasts.org/ — Lots of bitesize videos on everything about vim

vimtutor — On Windows find Vim Tutor via the Start Menu, or on Unix systems, execute $ vimtutor to begin an interactive tutorial for vim.

--

--