Vim Basics: Essential Commands and Practical Techniques
What you'll be able to do
- Switch modes and recover from a stuck Vim session unaided
- Choose between saving, discarding, and force-quitting
- Run search and replace safely in confirm mode
Prerequisites (read these first)
What You'll Learn
- You will be able to switch Vim modes and get yourself out of a stuck session.
- You will pick up the minimum workflow for movement, editing, and search/replace used in real work.
- You will be able to choose between saving, discarding, and force-quitting as the situation demands.
- You will be able to set up a comfortable
.vimrcfor any new server. - You will keep working even when only
viis installed on a remote box.
Who this is for: anyone who now has to SSH into a server and fix a config file. If you have ever opened Vim and failed to close it, this article is aimed squarely at you.
Terms defined up front
Every term Vim guides assume is defined once, here.
- A mode is the current state that decides what a keypress does. Vim keeps the state for moving and the state for typing separate.
- Normal mode is the state for moving, deleting, and copying. Some material calls it "command mode", but this article says "normal mode" to keep it distinct from command-line mode below.
- Insert mode is the state where a keypress puts that character into the text.
- Command-line mode is the state you enter with
:to type instructions such as save, quit, or replace. These are also called Ex commands. - A buffer is the file content Vim holds in memory. Editing the buffer does not change the file on disk yet — the file changes only when
:wwrites it. - Yank is Vim's name for a copy operation. Read it as "copy".
- A swap file is a hidden
.swpfile that stores edits as you go, so the content can be recovered after an abnormal exit.
Quick Summary (the practical workflow)
- After launching, always think in normal mode first (
Esc) - The editing loop is:
i→ edit →Esc→:w— four steps - If you get stuck, press
Esctwice, then:q!to force-quit - For config files, use
sudoedit, notsudo vim
Assumed environment
- OS: Ubuntu or any Linux
- Vim 8+ or Neovim (vi-compatibility quirks are noted)
- Mainly remote server work over SSH
1. Modes: 80% of the Battle
Conclusion: Vim's difficulty is its modes; learn normal, insert, visual, command-line first.
The single biggest reason beginners give up on Vim is modes. Once you internalize them, the rest is just memorizing commands.
| Mode | How to enter | What you can do |
|---|---|---|
| Normal | Esc |
Move, delete, copy |
| Insert | i / a / o |
Type text |
| Visual | v / V |
Select ranges |
| Command-line | : |
Save, quit, replace |
Rule of thumb: When anything weird happens, hit Esc twice to return to normal mode.
You can tell which mode you are in from the bottom-left of the screen: -- INSERT -- for insert mode, -- VISUAL -- for visual mode, and nothing at all for normal mode. Pressing Esc is always harmless, so press it whenever you are unsure.
1-1. Entering Insert Mode (Which Key to Use)
i # Insert before cursor a # Insert after cursor (great at end of line) o # Open new line below O # Open new line above I # Insert at start of line A # Insert at end of line
At first, just use i and o. Once comfortable, A (append at end) becomes a daily driver.
2. Save and Quit: The #1 Stuck Point
Conclusion: :w saves, :wq saves and quits, :q! discards; these three end the stuck problem.
This is where the "I can't escape Vim" memes come from. Memorize this section.
:w # Write (save) :q # Quit :wq # Save and quit :x # Save and quit (only writes if changed) ZZ # Same as :wq in normal mode :q! # Quit without saving :w !sudo tee % > /dev/null # Save a file you forgot to open with sudo (details in 2-1)
Plain :q refuses to quit if there are unsaved changes. Use :q! to discard, :wq to keep them.
:q! throws your edits away
The ! means "do it without asking". What happens when it goes wrong is unambiguous: quitting with :q! loses every edit you made, and undo cannot bring them back.
How to stay safe comes down to two habits.
- If you are unsure whether to keep or discard, save a copy first with
:w ~/backup.txt, then quit with:q!. - Before editing a config file, take a copy with
cp /etc/ssh/sshd_config ~/sshd_config.bak. Create the way back before you start.
2-1. Recovering from a sudo Mistake
Classic accident: open /etc/something with vim, edit it, then hit Permission denied on save.
:w !sudo tee % > /dev/null
%expands to the current filenameteewrites to disk;> /dev/nulldiscards stdout- After saving,
:q!(file is already on disk, so!is fine)
The proper fix: edit config files with sudoedit /etc/ssh/sshd_config (alias sudo -e). It opens a temp copy and writes back on exit.
3. Movement: Skip the Mouse
Conclusion: Move with hjkl, by word, line, screen, or search, all in normal mode.
These work in normal mode only. They do nothing in insert mode.
3-1. Character-Level
h j k l # left down up right
Mnemonic: j looks like a hook going down, k punches up.
3-2. Word, Line, Screen
w / b # Next / previous word start e # End of word 0 / ^ / $ # Start of line / first non-blank / end of line gg / G # Top / bottom of file :42 # Jump to line 42 Ctrl-d / Ctrl-u # Half-screen down / up Ctrl-f / Ctrl-b # Full-screen down / up
3-3. Search-Based Movement
/word # Search forward ?word # Search backward n / N # Next / previous match * # Search forward for word under cursor
Practical tip: When tailing a log, hit G to jump to the end, then ?ERROR to search backward.
4. Editing: The Bare Minimum
Conclusion: A few commands cover daily edits: x, dd, yy, p, u, and the repeat dot.
x # Delete one character dd # Delete a line (into clipboard) 3dd # Delete 3 lines dw # Delete a word d$ / D # Delete to end of line yy # Yank (copy) a line 3yy # Yank 3 lines p / P # Paste (after / before) u # Undo Ctrl-r # Redo . # Repeat last change
The most powerful command is . (dot). It repeats your last edit. Run dw once, move the cursor, hit . — same edit applied.
4-1. Numeric Prefixes
Almost any command takes a count prefix.
5j # Move 5 lines down 10x # Delete 10 characters 3yy # Yank 3 lines
5. Search and Replace: Daily Driver
Conclusion: Search with /pattern and replace with :%s/foo/bar/g; use gc to confirm safely.
5-1. Search
/pattern # Forward (regex allowed) ?pattern # Backward n / N # Next / previous
5-2. Replace (The Important One)
:s/foo/bar/ # First match on current line :s/foo/bar/g # All matches on current line :%s/foo/bar/g # All matches in the file :%s/foo/bar/gc # Same, with confirmation :5,10s/foo/bar/g # Only lines 5-10
The trailing g (global) means "every match on the line", c (confirm) means "ask about each one", and % sets the range to the whole file.
A global replace rewrites the text in one shot
:%s/foo/bar/g rewrites the entire file at once. What happens when it goes wrong is this:
- Too broad a pattern replaces text you never meant to touch. In a config file that breaks the syntax and the service stops starting.
- Right after the replace,
u(undo) still reverts it. Once you have saved with:wand left Vim, the undo history is gone and you cannot revert (unlessset undofileis enabled).
How to stay safe takes three steps.
- Search with
/foofirst and see how many matches there are and where. - Run the confirm mode,
:%s/foo/bar/gc, and decide per match withy(yes),n(no),a(all remaining),q(quit). - If you replaced something unintended, press
ubefore saving.
5-3. Regex Pitfalls
Vim's regex flavor differs subtly from POSIX extended regex.
:%s/\v(\w+)\s+\1/\1/g # \v enables "very magic" — closer to standard regex
With \v, you no longer need to escape (), +, or ?. Save it as muscle memory; it prevents a lot of head-scratching.
6. Multiple Files and Windows
Conclusion: Switch files with buffers and view them side by side with split windows.
6-1. Buffers (Multiple Files)
:e other.txt # Open another file :ls # List open buffers :b 2 # Switch to buffer 2 :bn / :bp # Next / previous buffer :bd # Close buffer
6-2. Split Windows
:sp file.txt # Horizontal split :vsp file.txt # Vertical split Ctrl-w w # Cycle through windows Ctrl-w q # Close current window Ctrl-w = # Equalize window sizes
A common setup: logs on one side, config file on the other. Pair with tmux over SSH for an even stronger workflow.
7. Visual Mode: Operate on a Selection
Conclusion: Select a range with v, V, or Ctrl-v, then delete, yank, indent, or replace.
v # Start character-wise selection V # Start line-wise selection Ctrl-v # Start block (rectangular) selection
With a selection active:
d # Delete y # Yank > # Indent < # Outdent :s/a/b/ # Replace within selection only
Block selection trick: To prefix multiple lines with # (comment them out), use Ctrl-v → select lines → I → # → Esc. It applies the prefix to all selected lines at once.
8. .vimrc: A Minimal Setup
Conclusion: Put a minimal ~/.vimrc with line numbers, search, and indent for comfort.
Write this in ~/.vimrc. It's small enough that you can retype it on a fresh server in 30 seconds.
" Basics
set number " Show line numbers
set ruler " Show cursor position
set showcmd " Show partial commands
set wildmenu " Better command completion
" Search
set hlsearch " Highlight matches
set incsearch " Incremental search
set ignorecase " Case-insensitive
set smartcase " But case-sensitive if pattern has uppercase
" Indent
set autoindent " Auto indent
set expandtab " Tab -> spaces
set tabstop=4 " Tab width
set shiftwidth=4 " Indent width
" Safety
set backup " Keep backup files
set backupdir=~/.vim/backup,/tmp
set undofile " Persistent undo
set undodir=~/.vim/undo
" UI
syntax on " Syntax highlighting
set background=dark " Assume dark terminal
Create the directories first: mkdir -p ~/.vim/backup ~/.vim/undo.
On a server with only vi (Vim's compatibility mode), some set options silently fail. Check :version to see what's available.
9. Escape Routes When Stuck
Conclusion: Stuck states like can't quit or can't save have mechanical escape routes.
Common stuck states and the mechanical fix.
9-1. Can't Quit
Esc Esc :q!
Always return to normal mode first, then force-quit.
9-2. Can't Save (Read-Only)
:set noreadonly :w
Or use the sudo trick: :w !sudo tee % > /dev/null.
9-3. Frozen Screen
Ctrl-q # Resume a terminal stopped by Ctrl-s
Ctrl-s pauses the terminal itself — not a Vim problem.
9-4. A Column of ~ Down the Left Edge
This is not a fault. ~ is Vim's ordinary marker for "there is no line here", and it always fills the area below the end of the file. No action is needed.
Likewise, finding extra files such as file.txt~ after editing is not a fault. Those are backup files created by set backup in your .vimrc (covered below), which is a different thing from a swap file. Delete them if you do not want them.
9-5. E325: ATTENTION on Startup
A swap file (.swp) is left over. It is a sign that Vim did not exit cleanly last time, or that someone else has the same file open.
E325: ATTENTION Found a swap file by the name ".file.txt.swp"
ls -la .*.swp :recover # Run inside Vim
Review what :recover restores, save anything you need, and only then run rm .file.txt.swp. Swap file names take the form ". + original filename + .swp".
Never delete a swap file reflexively
Deleting .swp also deletes the unsaved edits parked inside it. What happens when it goes wrong is twofold.
- You destroy your own unsaved work — content
:recovercould have retrieved. - If someone else is editing that very file right now, you break their session.
How to stay safe is to confirm two things before deleting.
ps aux | grep vim # is anyone editing right now?
Delete only once no editing process exists and you have confirmed the :recover content is not needed.
10. vi vs Vim vs Neovim
Conclusion: vi is usually Vim's compat mode, Vim is the standard, Neovim is a modern fork.
| Name | What it really is | Notes |
|---|---|---|
| vi | Usually Vim running in vi-compatible mode | Some settings disabled |
| Vim | Vi IMproved | The de facto standard |
| Neovim | A fork of Vim | Lua config, built-in LSP, modern internals |
which vi ls -l $(which vi)
/usr/bin/vi lrwxrwxrwx 1 root root 20 Feb 15 2024 /usr/bin/vi -> /etc/alternatives/vi
What sits to the right of -> is the real binary. On Ubuntu it goes through /etc/alternatives/vi to vim.basic or vim.tiny. Which one it is decides what settings are available.
Minimal Ubuntu installs may only have vim-tiny. Install the full version with sudo apt install vim.
11. Summary: The Workflow You'll Use Tomorrow
Copy-paste template: minimum daily workflow
# 1. Open vim file.txt # 2. Move in normal mode gg # Top of file /keyword # Search # 3. Switch to insert mode i # Start editing (edit) Esc # Back to normal # 4. Save and quit :wq # If you mess up :q! # Discard and quit
Completion Checklist
- [ ] Told which mode you are in from the bottom-left indicator
- [ ] Chose deliberately between
:wq(save and quit) and:q!(discard and quit) - [ ] Checked the targets with
/patternbefore a global replace - [ ] Edited config files via
sudoedit, or after taking a backup - [ ] Ran
ps aux | grep vimbefore deleting a.swpfile
Don't do this
- Typing
:wqwhile still in insert mode (you write:wqinto the file) - Opening a file with
sudo vim /etc/...and getting stuck on save — usesudoeditinstead - Reflexively deleting
.swpfiles — someone may be editing - Bloating your
.vimrc— it stops being portable across servers