Lazygit
6 min read
Terminal UI for git. Makes complex git operations (interactive rebase, partial staging, bisect, worktrees, cherry-pick) accessible without leaving the terminal.
Install
sh
# macOS
brew install lazygit
# Arch Linux
sudo pacman -S lazygit
# Debian 13+ / Ubuntu 25.10+
sudo apt install lazygit
# Fedora
sudo dnf copr enable dejan/lazygit && sudo dnf install lazygit
# Windows
scoop install lazygit
winget install JesseDuffield.lazygit
# FreeBSD
pkg install lazygit
# Nix
nix run nixpkgs#lazygit
nix-shell -p lazygit
# NixOS: environment.systemPackages = [ pkgs.lazygit ]
# Go
go install github.com/jesseduffield/lazygit@latest
Usage
sh
lazygit # open in current repo
lazygit -p /path/to/repo # explicit path
Layout
Five side panels (jump with 1–5):
| # | Panel | Contents |
|---|---|---|
| 1 | Status | Repo status, recent repos |
| 2 | Files | Working tree, staging area |
| 3 | Branches | Local branches / Remotes / Tags / Worktrees (tabs) |
| 4 | Commits | Commit log / Reflog (tabs) |
| 5 | Stash | Stash entries |
Navigate tabs within a panel with [ / ]. The main panel (right) shows the diff or content for the selected item.
Keybindings
Global
| Key | Action |
|---|---|
1–5 | Jump to panel |
[ / ] | Previous / next tab |
P | Push |
p | Pull |
R | Refresh |
z / Z | Undo / Redo (via reflog) |
+ / _ | Cycle screen modes (normal / half / full) |
| | Cycle pagers |
m | Merge/rebase options |
W | Diff options |
<c-p> | Custom patch options |
: | Execute shell command |
? | Keybinding help |
q | Quit |
Files Panel
| Key | Action |
|---|---|
space | Stage / unstage file |
a | Stage all |
enter | Stage individual lines / enter directory |
d | Discard changes |
D | Reset (nuke) options |
c | Commit |
A | Amend last commit |
C | Commit using editor |
w | Commit without pre-commit hook |
<c-f> | Find base commit for fixup |
e | Edit file |
i | Ignore / exclude file |
s / S | Stash / stash options |
` | Toggle file tree view |
Staging View (main panel)
| Key | Action |
|---|---|
space | Stage / unstage selected line |
v | Toggle range select |
a | Toggle hunk |
d | Discard selection |
← / → | Previous / next hunk |
tab | Switch staged ↔ unstaged |
E | Edit hunk in editor |
Commits Panel
| Key | Action |
|---|---|
i | Start interactive rebase |
s | Squash into commit below |
f | Fixup into commit below |
F | Create fixup commit for this commit |
S | Apply all fixup commits above |
r / R | Reword / reword with editor |
d | Drop commit |
e | Edit (pause rebase here) |
p | Pick (during rebase) |
<c-j> / <c-k> | Move commit down / up |
B | Mark as base commit for rebase |
A | Amend with staged changes |
t | Revert commit |
T | Tag commit |
n | New branch from commit |
N | Move commits to new branch |
C / V | Copy (cherry-pick) / Paste |
b | Bisect options |
g | Reset options |
<shift-w> | Mark for diff comparison |
G | Open PR in browser |
Branches Panel
| Key | Action |
|---|---|
space | Checkout |
n | New branch |
d | Delete branch |
r | Rebase onto selected |
M | Merge options |
f | Fast-forward |
R | Rename |
o / O | Create PR / PR options |
G | Open PR in browser |
<c-y> | Copy PR URL |
i | Git flow options |
w | Worktree options |
- | Checkout previous branch |
Other Panels
| Panel | Key | Action |
|---|---|---|
| Stash | space / g | Apply / Pop |
| Stash | d | Drop |
| Stash | n | New branch from stash |
| Stash | r | Rename stash |
| Worktrees | n | New worktree |
| Worktrees | space | Switch to worktree |
| Worktrees | d | Remove worktree |
| Remotes | n / d / e | New / Remove / Edit remote |
| Remotes | f | Fetch from remote |
Configuration
File Locations
| Platform | Path |
|---|---|
| Linux | ~/.config/lazygit/config.yml |
| macOS | ~/Library/Application Support/lazygit/config.yml |
| Windows | %LOCALAPPDATA%\lazygit\config.yml |
| Repo-specific | <repo>/.git/lazygit.yml |
| Hierarchical | .lazygit.yml in any parent directory |
Merge multiple configs: LG_CONFIG_FILE="$HOME/.base.yml,$HOME/.theme.yml" lazygit
Add JSON schema support to get editor completion:
yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/jesseduffield/lazygit/master/schema/config.json
Key Options
yaml
gui:
nerdFontsVersion: "3" # "" | "2" | "3" — enable icons
showFileIcons: true
border: rounded # rounded | single | double | hidden | bold
filterMode: fuzzy # substring | fuzzy
sidePanelWidth: 0.3333
mainPanelSplitMode: flexible # horizontal | vertical | flexible
showDivergenceFromBaseBranch: arrowAndNumber
statusPanelView: dashboard # dashboard | allBranchesLog
language: auto
theme:
activeBorderColor: ["green", "bold"]
selectedLineBgColor: ["blue"]
unstagedChangesColor: ["red"]
authorColors:
"Alice": "red"
branchColorPatterns:
"^feat/": "cyan"
git:
autoFetch: true
autoRefresh: true
diffContextSize: 3
ignoreWhitespaceInDiffView: false
mainBranches: ["main", "master"]
skipHookPrefix: "WIP"
log:
order: topo-order # date-order | author-date-order | topo-order
showGraph: always # always | never | when-maximised
localBranchSortOrder: date # date | recency | alphabetical
os:
editPreset: "nvim" # vim | nvim | emacs | nano | vscode | zed | helix | …
# or explicit:
edit: "nvim {{filename}}"
editAtLine: "nvim +{{line}} {{filename}}"
Custom Pagers
Cycle between pagers with |. Multiple pagers can be defined.
yaml
git:
pagers:
# delta
- pager: delta --dark --paging=never --line-numbers
# delta with editor hyperlinks (click line numbers to jump)
- pager: delta --dark --paging=never --hyperlinks --hyperlinks-file-link-format="lazygit-edit://{path}:{line}"
# diff-so-fancy
- pager: diff-so-fancy
# ydiff (needs colorArg: never)
- colorArg: never
pager: ydiff -p cat -s --wrap --width={{columnWidth}}
# difftastic (external diff)
- externalDiffCommand: difft --color=always
# use git's own difftool config
- useExternalDiffGitConfig: true
Custom Commands
Defined in a customCommands array. Bound to a key in a given context.
Full Example
yaml
customCommands:
# Open GitHub URL for selected commit
- key: "o"
context: "commits"
description: "Open commit on GitHub"
command: 'open "https://github.com/user/repo/commit/{{.SelectedCommit.Hash}}"'
# New branch with ticket prefix prompt
- key: "b"
context: "localBranches"
description: "New branch with ticket"
prompts:
- type: input
title: "Ticket number"
key: Ticket
- type: input
title: "Branch name"
key: Name
command: "git checkout -b PROJ-{{.Form.Ticket}}/{{.Form.Name}}"
# Force push with confirmation
- key: "F"
context: "localBranches"
description: "Force push"
prompts:
- type: confirm
title: "Force push?"
body: "This will overwrite the remote branch."
command: "git push --force-with-lease"
loadingText: "Force pushing..."
# Menu-driven rebase action
- key: "R"
context: "commits"
description: "Rebase action"
prompts:
- type: menu
title: "Action"
key: Action
options:
- name: "squash"
value: "squash"
key: s
- name: "fixup"
value: "fixup"
key: f
command: "echo {{.Form.Action}} {{.SelectedCommit.Hash}}"
output: popup
Contexts
status, files, worktrees, submodules, localBranches, remotes, remoteBranches, tags, commits, reflogCommits, subCommits, commitFiles, stash, global
Comma-separate for multiple: context: "localBranches,remoteBranches"
Template Variables
| Variable | Description |
|---|---|
{{.SelectedCommit.Hash}} | Selected commit hash |
{{.SelectedFile.Name}} | Selected file path |
{{.SelectedLocalBranch.Name}} | Selected local branch |
{{.SelectedRemoteBranch.Name}} | Selected remote branch |
{{.SelectedTag.Name}} | Selected tag |
{{.SelectedStashEntry.Index}} | Stash index |
{{.SelectedPath}} | Selected file/path |
{{.CheckedOutBranch.Name}} | Currently checked out branch |
{{.SelectedCommitRange.From}} | First commit in range |
{{.SelectedCommitRange.To}} | Last commit in range |
{{.Form.KEY}} | Value from a prompt with key: KEY |
{{quote .SelectedFile.Name}} | Platform-safe quoted path |
{{runCommand "git rev-parse HEAD"}} | Run subprocess, returns stdout |
Output Modes
| Mode | Description |
|---|---|
none | Discard output |
terminal | Suspend lazygit, run interactively |
log | Stream to command log panel |
logWithPty | Like log but with terminal color support |
popup | Display result in overlay |
yaml
customCommands:
- key: X
commandMenu:
- key: c
command: "git cherry-pick {{.SelectedCommit.Hash}}"
context: commits
description: "Cherry pick"
- key: r
command: "git revert {{.SelectedCommit.Hash}}"
context: commits
description: "Revert"
Features
Interactive Rebase
Press i in the Commits panel. Then on any commit: s squash, f fixup, d drop, r reword, e edit, <c-k>/<c-j> move. Continue with m → continue. One-off actions work without explicitly starting a rebase.
Partial Staging
In the Files panel, press enter on a file to open staging view. Stage individual lines with space, select ranges with v, toggle hunks with a.
Cherry-pick
C on a commit to copy, V to paste (cherry-pick). <c-r> to reset the cherry-pick selection.
Amend Old Commit
Stage your changes, then A on any commit in the Commits panel. Runs an interactive rebase in the background.
Bisect
Press b in the Commits panel to mark a commit as good/bad and begin git bisect.
Worktrees
Access from the Branches panel tabs or w from various panels. Create worktrees from any branch; switch between them without stashing.
Custom Patches
Enter a commit's files with enter, then a file's diff with enter. Add lines with space, then <c-p> for patch options (remove from commit, apply in reverse, split commit, etc.).
Rebase from Marked Base
B to mark a base commit, then rebase onto another branch — only commits from your feature branch are brought along.
PR Integration
Requires gh CLI and gh auth login. In the Branches panel, branches with open PRs show a GitHub icon. G opens the PR in the browser; <c-y> copies the PR URL.
Commit Graph
Enlarge with +/_ to cycle screen modes. Colors correspond to commit authors; parent commits are highlighted as you navigate.
Diff Comparison
<shift-w> on a commit or branch to mark it, then navigate to another commit/branch to diff against it.
Undo / Redo
z undoes the last action (via reflog — covers commits and branches, not working tree or stash). Z redoes.
Commit Colors
| Color | Meaning |
|---|---|
| Green | Included in the main branch |
| Yellow | Not in the main branch |
| Red | Not pushed to upstream |