vimtricks.wiki Concise Vim tricks, one at a time.

How do I move all lines matching a pattern to the top or bottom of a file?

Answer

:g/pattern/m 0

Explanation

The :global command combined with :move lets you restructure a file by relocating all lines that match a pattern. This is invaluable for reorganizing imports, grouping related definitions, or pulling TODOs and FIXMEs to the top of a file for review.

How it works

  • :g/pattern/ — iterates over every line matching pattern
  • m 0 — moves the current line to after line 0 (i.e., the top of the file)
  • Each matching line is moved in order, so the last match ends up on line 1. The result is that all matching lines appear at the top in their original relative order
  • Use m $ to move matching lines to the bottom instead

Example

Given a file with scattered TODO comments:

func init() {
// TODO: add validation
func process() {
// TODO: handle errors
func cleanup() {
// TODO: add logging

Running :g/TODO/m 0 produces:

// TODO: add validation
// TODO: handle errors
// TODO: add logging
func init() {
func process() {
func cleanup() {

Tips

  • Combine with :v (inverse global) to move non-matching lines instead: :v/pattern/m $
  • Use a range to limit scope: :10,50g/import/m 9 moves imports in lines 10-50 to just before line 10
  • Pair with :sort after moving for alphabetical ordering: :g/^import/m 0 then :1,/^[^i]/sort
  • A single undo (u) reverses the entire operation since :g batches all moves

Next

How do I ignore whitespace changes when using Vim's diff mode?