Install

# Debian / Ubuntu — the package may be old; prefer the upstream
LG_VER=0.43.1
curl -L -o /tmp/lazygit.tgz \
    "https://github.com/jesseduffield/lazygit/releases/download/v${LG_VER}/lazygit_${LG_VER}_Linux_x86_64.tar.gz"
tar -xzf /tmp/lazygit.tgz -C /tmp
sudo install /tmp/lazygit /usr/local/bin

# macOS
brew install lazygit

# Arch
sudo pacman -S lazygit

# Or via mise (see /tutorials/mise-polyglot-runtime-versions.html)
mise use -g lazygit@latest

Verify:

lazygit --version

The five panels

Open a Git repo and run lazygit. The layout:

┌──────────────────┬─────────────────────────────────┐
│ Status           │                                 │
│ Files            │                                 │
│ Local branches   │  Main panel (diff / log / etc.) │
│ Commits          │                                 │
│ Stash            │                                 │
└──────────────────┴─────────────────────────────────┘

Tab / Shift-Tab cycles between the five left panels. Each panel has its own keybindings shown at the bottom of the screen.

The keystrokes worth memorizing

# Universal
?              Show help & keybindings for the current panel
q              Quit
Esc            Back / cancel
:              Type a raw git command (escape hatch)

# Files panel
space          Stage / unstage a file
a              Stage / unstage ALL files
d              Discard changes (interactive)
e              Edit the file in $EDITOR
enter          Open the file's hunks for line-by-line staging
c              Commit (opens $EDITOR for the message)
C              Commit with the editor (alternate)
A              Amend last commit

# In the hunks view (after pressing enter on a file)
space          Stage / unstage individual lines or hunks
v              Visual select range, then stage that range
enter          Same idea but selects whole hunk
J / K          Scroll between hunks

# Local branches panel
n              New branch from current HEAD
space          Checkout selected branch
d              Delete (with confirmation)
M              Merge selected into current
r              Rebase current onto selected

# Commits panel
enter          Show the commit diff
space          Cherry-pick (mark / paste)
d              Drop commit (during rebase)
r              Reword (during rebase)
e              Edit (split / amend; during rebase)
s              Squash into previous (during rebase)
f              Fixup into previous

# Stash panel
s              Stash current changes (with message)
space          Apply stash
g              Pop stash (apply + drop)
d              Drop stash

Interactive rebase, the easy way

The killer use-case. From the Commits panel:

  1. Cursor onto the commit you want to rebase onto (e.g. origin/main's last shared commit).
  2. Press e. This starts an interactive rebase — lazygit shows the to-be-rebased commits highlighted.
  3. Navigate the list, press d to drop, r to reword, s to squash into the previous, f to fixup, e to edit.
  4. Press m to start the actual rebase. Lazygit walks through it; if there's a conflict, you go to the Files panel to resolve, then m to continue.

Compared to typing git rebase -i HEAD~10 and editing a text file with single-letter commands, lazygit shows you the diffs as you go and lets you reorder commits with ctrl-j / ctrl-k.

Hunk-level staging

The other killer feature. In the Files panel, press enter on a modified file:

  • Lazygit shows the file's diff, hunk by hunk.
  • space stages / unstages the current hunk.
  • v enters visual mode — select a range of lines, space stages just those lines.

This is the same as git add -p + s (split), but visual: you see the file's full context, scroll up and down, and stage what you mean.

Custom commands

Configure repeatable workflows in ~/.config/lazygit/config.yml:

customCommands:
  - key: "C"
    context: "files"
    command: "git commit --signoff -m '{{ .Form.Message }}'"
    description: "Commit with sign-off"
    prompts:
      - type: "input"
        title: "Commit message:"
        key: "Message"

  - key: "P"
    context: "global"
    command: "git push --force-with-lease"
    description: "Force push (with-lease)"
    confirmation: "About to force-push with --force-with-lease. Continue?"

The bound key becomes a single-keystroke action in the matching context. --force-with-lease is the right kind of force-push; the confirmation prompt is the speed bump.

Integration with editors

  • Neovim — the lazygit.nvim plugin opens lazygit in a floating window from any buffer.
  • VS Code — the Lazygit VS Code extension runs it in a panel.
  • Helix — just :sh lazygit opens it inline (or set up a key binding).

Aliases that pay off

# ~/.bashrc / ~/.zshrc
alias lg='lazygit'

Inside Git repos, lg launches the TUI; outside, it does nothing. After a week, this is the only way most operations happen.

When lazygit isn't the right tool

  • For scripted git operations — obviously, write the script.
  • For history-rewriting that needs precision (BFG-style large-file removal, filter-branch / git-filter-repo) — use the CLI tools designed for it.
  • For PR review — lazygit shows local commits but doesn't integrate with GitHub / GitLab PR threads. Pair with the GitHub CLI (gh) or a similar tool.

For 90% of "I want to do something in git, ideally without thinking about flags," lazygit is faster than the CLI and faster than most GUI clients.