# Lazygit User Guide

Lazygit is a terminal user interface (TUI) for git, written in Go. It replaces the need to memorize and type complex git commands by presenting an interactive, keyboard-driven interface for staging, committing, branching, rebasing, merge conflict resolution, stashing, cherry-picking, bisecting, worktree management, and more. If you can use git from the command line, lazygit lets you do the same things faster and with less friction.

---

## 1. Quick Start

### Open lazygit in a repository

```bash
cd /path/to/your/repo
lazygit
```

That's it. Lazygit opens with five main panels arranged vertically on the left and a diff/detail view on the right:

| Panel | Key | What it shows |
|-------|-----|---------------|
| Status | `1` | Current branch, repo name, recent activity |
| Files | `2` | Working directory changes (staged and unstaged) |
| Branches | `3` | Local branches, remotes, tags, worktrees (as tabs) |
| Commits | `4` | Commit log for the current branch |
| Stash | `5` | Stashed changes |

Press the number key to jump directly to any panel. Use `<tab>` to cycle through panels, or `h`/`l` (left/right arrow keys) to move between them.

### The 60-second workflow

1. Open lazygit in your repo
2. Navigate to the **Files** panel (`2`)
3. Use `j`/`k` to select a file, press `<space>` to stage it
4. Press `c` to open the commit prompt, type your message, press `<enter>`
5. Press `P` to push

> [!TIP]
> Press `a` in the Files panel to stage or unstage **all** files at once. This is the fastest way to commit everything in your working directory.

### Navigating the interface

Lazygit follows vim-style navigation throughout:

| Key | Action |
|-----|--------|
| `j` / `<down>` | Move down |
| `k` / `<up>` | Move up |
| `h` / `<left>` | Previous panel |
| `l` / `<right>` | Next panel |
| `<enter>` | Go into / confirm |
| `<esc>` | Go back / cancel |
| `q` | Quit lazygit |
| `?` | Open options/help menu |

Press `?` on any panel to see context-sensitive keybindings for that panel.

---

## 2. Installation

### Package managers

#### macOS

```bash
# Homebrew
brew install lazygit

# MacPorts
sudo port install lazygit
```

#### Linux

```bash
# Arch Linux
pacman -S lazygit

# Fedora / RHEL (COPR)
sudo dnf copr enable atim/lazygit -y
sudo dnf install lazygit

# Ubuntu / Debian (via Snap or binary release)
sudo snap install lazygit

# Void Linux
sudo xbps-install -S lazygit

# Nix
nix-env -iA nixpkgs.lazygit
```

#### Windows

```powershell
# Scoop
scoop install lazygit

# Chocolatey
choco install lazygit

# Winget
winget install -e --id=JesseDuffield.Lazygit
```

#### From source

```bash
go install github.com/jesseduffield/lazygit@latest
```

> [!IMPORTANT]
> Lazygit requires **git version 2.32.0 or later**. Run `git --version` to check. Older git versions will cause unexpected behavior or crashes.

### Verifying installation

```bash
lazygit --version
```

This prints the version, build date, commit hash, build source, and OS/architecture.

> [!WARNING]
> If you install from source with `go install`, ensure your `$GOPATH/bin` (or `$GOBIN`) is in your `PATH`. Otherwise the `lazygit` command will not be found.

---

## 3. Configuration

### Config file location

Lazygit reads its configuration from a YAML file:

| Platform | Default path |
|----------|-------------|
| Linux / macOS | `~/.config/lazygit/config.yml` |
| Windows | `%APPDATA%\lazygit\config.yml` |

The path follows the XDG Base Directory specification (`$XDG_CONFIG_HOME/lazygit/config.yml`). Lazygit also checks the legacy path `~/.config/jesseduffield/lazygit/config.yml` for backward compatibility.

State information (e.g., recent repos) is stored separately at `$XDG_STATE_HOME/lazygit/state.yml`.

### Overriding config location

Use the `LG_CONFIG_FILE` environment variable to point to one or more custom config files (comma-separated):

```bash
LG_CONFIG_FILE="~/dotfiles/lazygit.yml,~/lazygit-local.yml" lazygit
```

Or use the CLI flag:

```bash
lazygit --use-config-file ~/dotfiles/lazygit.yml
```

To override the entire config directory:

```bash
lazygit --use-config-dir ~/my-lazygit-config/
```

### Printing the defaults

To see the full default configuration:

```bash
lazygit --config
```

To find your config directory:

```bash
lazygit --print-config-dir
```

### Key configuration options

Below are some of the most commonly customized settings. For the full configuration reference, see the **Admin Guide**.

#### Editor preset

Set `os.editPreset` to have lazygit open files in your preferred editor. Supported values:

| Preset | Editor |
|--------|--------|
| `vi` | Vi |
| `vim` | Vim |
| `nvim` | Neovim |
| `nvim-remote` | Neovim remote |
| `lvim` | LunarVim |
| `emacs` | Emacs |
| `micro` | Micro |
| `nano` | Nano |
| `kakoune` | Kakoune |
| `helix` | Helix |
| `vscode` | VS Code |
| `sublime` | Sublime Text |
| `bbedit` | BBEdit |
| `xcode` | Xcode |
| `zed` | Zed |
| `acme` | Acme |

Example config:

```yaml
os:
  editPreset: nvim
```

#### Language

Lazygit supports multiple interface languages. Set `gui.language` in your config:

```yaml
gui:
  language: auto
```

Supported values: `auto`, `en`, `zh-CN`, `zh-TW`, `pl`, `nl`, `ja`, `ko`, `ru`, `pt`.

#### Mouse support

Mouse support is enabled by default. To disable:

```yaml
gui:
  mouseEvents: false
```

#### Nerd Fonts icons

If you use a Nerd Font in your terminal, enable icons:

```yaml
gui:
  nerdFontsVersion: "3"
```

Supported values: `"2"` for Nerd Fonts v2, `"3"` for Nerd Fonts v3.

#### Custom pager

Lazygit works with external diff tools like delta, diff-so-fancy, and difftastic. Configure them under `git.paging`:

```yaml
git:
  paging:
    colorArg: always
    pager: delta --dark --paging=never
```

#### Non-repository behavior

The `notARepository` setting controls what happens when you open lazygit outside a git repo:

| Value | Behavior |
|-------|----------|
| `prompt` | Ask whether to initialize or open a recent repo (default) |
| `create` | Automatically run `git init` |
| `skip` | Open the most recently used repo |
| `quit` | Exit immediately |

```yaml
notARepository: prompt
```

### Environment variables

| Variable | Purpose |
|----------|---------|
| `LG_CONFIG_FILE` | Comma-separated list of config file paths |
| `CONFIG_DIR` | Override config directory |
| `LAZYGIT_LOG_PATH` | Custom log file path |
| `GIT_WORK_TREE` | Git work tree path |
| `GIT_DIR` | Git directory path |
| `DEBUG` | Set to `TRUE` to enable debug mode |
| `LOG_LEVEL` | Log level: `debug`, `info`, `warn`, `error` |

---

## 4. Core Usage

### Understanding the layout

Lazygit divides the terminal into two regions:

- **Side panels** (left): the five main panels stacked vertically
- **Main view** (right): shows diffs, file contents, commit details, or merge conflict views depending on context

The panels can be displayed in different screen modes. Press `+` to cycle forward through modes (normal, half, full) or `_` to cycle backward.

> [!NOTE]
> In **full screen mode**, the side panels are hidden and the main view takes the entire terminal. This is useful when reviewing large diffs. Press `_` to return to normal mode.

#### Side panel tabs

Some panels contain tabs. For example, the **Branches** panel has four tabs:

- Local Branches
- Remotes
- Tags
- Worktrees

Press `]` to move to the next tab and `[` for the previous tab within a panel.

### File tree vs. flat view

The Files panel can show changes as a flat list or as a directory tree. Press the backtick key (`` ` ``) to toggle between views. Tree view is helpful in large repositories where changes span many directories.

### Staging changes

Navigate to the **Files** panel and select a file:

| Key | Action |
|-----|--------|
| `<space>` | Stage/unstage the selected file |
| `a` | Stage/unstage all files |
| `<enter>` | Open file to stage individual lines or hunks |

When you press `<enter>` on a file, the main view switches to a **staging view** where you can:

| Key | Action |
|-----|--------|
| `<space>` | Stage/unstage selected line |
| `a` | Toggle select entire hunk |
| `v` | Enter range select mode |

> [!TIP]
> Use range select (`v`) in the staging view to select multiple lines, then press `<space>` to stage them all. This gives you precise control over what goes into each commit.

### Committing

From the Files panel:

| Key | Action |
|-----|--------|
| `c` | Commit staged changes (inline message prompt) |
| `C` | Commit with your configured editor |
| `w` | Commit without running git hooks |
| `A` | Amend the last commit |

After pressing `c`, type your commit message and press `<enter>` to confirm.

### Pushing and pulling

These bindings work from any panel:

| Key | Action |
|-----|--------|
| `P` (shift) | Push to remote |
| `p` | Pull from remote |
| `f` | Fetch from remote (in Files panel) |

> [!IMPORTANT]
> Push is `P` (uppercase/shift) and pull is `p` (lowercase). Mixing these up is the most common mistake for new users.

### Branching

In the **Branches** panel:

| Key | Action |
|-----|--------|
| `n` | Create a new branch |
| `<space>` | Checkout selected branch |
| `c` | Checkout branch by name |
| `R` | Rename branch |
| `d` | Delete branch |
| `M` | Merge selected branch into current |
| `r` | Rebase current branch onto selected |
| `F` | Force checkout |
| `f` | Fast-forward current branch to match selected |
| `u` | Set/change upstream |
| `s` | Change sort order |

### Searching and filtering

Press `/` to start a search within the current panel. Use `n` to jump to the next match and `N` for the previous match.

Press `<c-s>` (Ctrl+S) to open the filtering menu, which lets you filter commits by path or other criteria.

### Undo and redo

Lazygit maintains an undo/redo stack for many operations:

| Key | Action |
|-----|--------|
| `z` | Undo |
| `Z` | Redo |

This works for commits, branch checkouts, and other ref-changing operations. It uses git's reflog under the hood.

### Executing shell commands

Press `:` to open a shell command prompt. Type any shell command and press `<enter>` to execute it. The output appears in the main view.

### Copying to clipboard

Press `<c-o>` (Ctrl+O) to copy the currently selected item to your clipboard. In the Commits panel, press `y` to copy commit attributes (hash, message, URL, etc.).

### Opening recent repos

Press `<c-r>` (Ctrl+R) to open a list of recently visited repositories and switch between them.

---

## 5. Common Tasks

### Recipe 1: Stage specific lines from a file

1. Go to the Files panel (`2`)
2. Select the modified file and press `<enter>`
3. In the staging view, navigate to the lines you want
4. Press `v` to enter range select, select lines with `j`/`k`
5. Press `<space>` to stage selected lines
6. Press `<esc>` to return to the Files panel
7. Press `c` to commit

### Recipe 2: Interactive rebase (reorder, squash, edit commits)

1. Go to the Commits panel (`4`)
2. Select the commit where you want to start the rebase
3. Press `i` to begin an interactive rebase
4. Use `<c-j>` and `<c-k>` to move commits up and down
5. Press `s` on a commit to mark it for squash
6. Press `f` to mark as fixup (squash without keeping the message)
7. Press `r` to reword a commit message
8. Press `p` to pick (keep as-is)
9. Navigate to the bottom and confirm the rebase

### Recipe 3: Resolve merge conflicts

1. When a merge or rebase produces conflicts, lazygit shows conflicted files in the Files panel
2. Select a conflicted file and press `<enter>`
3. The main view shows conflict markers with incoming and current changes highlighted
4. Use `<space>` to select which version to keep
5. Press `b` to pick both versions
6. After resolving all conflicts in a file, press `<esc>` to return
7. Stage the resolved file with `<space>` and continue the merge/rebase

### Recipe 4: Cherry-pick commits between branches

1. Go to the Commits panel (`4`)
2. Select the commit(s) you want to cherry-pick
3. Press `C` (shift+C) to copy the commit
4. For multiple commits, use range select (`v`) then `C`
5. Switch to the target branch in the Branches panel
6. Press `V` (shift+V) to paste (apply) the cherry-picked commits
7. Press `<c-R>` to clear the cherry-pick selection when done

### Recipe 5: Stash and restore changes

**Stash everything:**

1. In the Files panel, press `s` to stash all changes

**Stash with options:**

1. Press `S` (shift) to see stash options (stash staged only, stash with message, etc.)

**Restore a stash:**

1. Go to the Stash panel (`5`)
2. Select the stash entry
3. Press `<space>` to apply it (keeps the stash)
4. Press `g` to pop it (applies and removes the stash)

### Recipe 6: Create and push a tag

1. Go to the Commits panel (`4`)
2. Select the commit to tag
3. Press `T` to create a tag, enter the tag name
4. Go to the Branches panel (`3`), then the Tags tab (`]` to cycle tabs)
5. Select the tag and press `P` to push it to the remote

### Recipe 7: Git bisect to find a bug

1. Go to the Commits panel (`4`)
2. Press `b` to open bisect options
3. Mark the current commit as bad
4. Navigate to a known good commit and mark it as good
5. Lazygit walks you through the bisect, checking out commits for you to test
6. Mark each commit as good or bad until the culprit is found

### Recipe 8: Work with multiple worktrees

1. Go to the Branches panel (`3`)
2. Navigate to the **Worktrees** tab (press `]` until you reach it)
3. Press `n` to create a new worktree
4. Select an existing worktree and press `<enter>` to switch to it

### Recipe 9: Manage submodules

1. In the Files panel, navigate to the Submodules tab
2. Press `i` to initialize submodules
3. Press `u` to update submodules
4. Press `b` for bulk operations (init all, update all, deinit all)
5. Press `<enter>` on a submodule to open lazygit inside it

### Recipe 10: Amend a specific commit (not just the last one)

1. Go to the Commits panel (`4`)
2. Stage the changes you want to add in the Files panel
3. Return to the Commits panel and select the target commit
4. Press `A` to amend the staged changes into that commit

> [!NOTE]
> Amending a commit that is not the most recent triggers an automatic interactive rebase. This rewrites history, so avoid doing this on commits that have already been pushed to a shared branch.

### Recipe 11: Build a patch from an old commit

1. Go to the Commits panel and select a commit
2. Press `<enter>` to view its files
3. Select a file and press `<enter>` to view the diff
4. Use `<space>` to select lines or hunks to include in your patch
5. Press `<c-p>` to open the patch options menu
6. Choose to apply the patch, create a new commit from it, or other options

### Recipe 12: Reset a branch to a previous state

1. In the Files panel, press `D` to view reset options
2. Choose soft reset (keep changes staged), mixed (keep changes unstaged), or hard (discard everything)

Alternatively, in the Commits panel:

1. Select the commit to reset to
2. Press `g` to open reset options
3. Choose the reset type

### Recipe 13: View and compare diffs

1. Press `W` to open the diffing menu
2. Select a branch or commit to diff against
3. The main view updates to show the diff
4. Press `<c-w>` to toggle whitespace visibility in diffs
5. Press `}` / `{` to increase or decrease diff context lines

### Recipe 14: Create a fixup commit

1. Stage your changes in the Files panel
2. Press `<c-f>` to find the base commit that your changes fix
3. Lazygit creates a fixup commit automatically targeting that base commit
4. Later, use interactive rebase to autosquash fixup commits

---

## 6. Troubleshooting

> [!WARNING]
> Many issues are terminal-specific. If lazygit behaves unexpectedly, try running it in a different terminal emulator to isolate the problem.

### Lazygit crashes on startup

**Symptoms:** Immediate crash or panic when launching lazygit.

**Possible causes and solutions:**

- **Terminal incompatibility:** Some newer terminals may have compatibility issues. If lazygit crashes in one terminal (e.g., Ghostty) but works in another (e.g., VS Code's integrated terminal), the issue is terminal-specific. Check for updates to both lazygit and the terminal. (See GitHub issue #5511)
- **Symlinked directory:** Opening lazygit when your current directory is a symlink to a git repo can cause crashes. `cd` to the real path instead. (See GitHub issue #3015)
- **Corrupt config:** Rename `~/.config/lazygit/config.yml` temporarily and retry with defaults.
- **Corrupt state file:** Delete `$XDG_STATE_HOME/lazygit/state.yml` to reset state.

### Keybinding not working during search

When the search prompt is active (`/`), some keybindings like `q` (quit) are consumed by the search input rather than their normal action. Press `<esc>` to close search first, then use the keybinding. (See GitHub issue #5520)

### Option+Enter / Alt+Enter appends extra characters

On macOS, using Option+Enter to commit from the title field may insert an extra character (like "m") into the description field. This is a known terminal/keybinding interaction issue. Use `<enter>` instead, or commit via `C` to use your external editor. (See GitHub issue #5521)

### Moving commits triggers unexpected panel switch

When using `<c-j>` to move a commit down during an interactive rebase, the view may sometimes jump to the diff files section instead. If this happens, press `<esc>` to return to the Commits panel and retry. (See GitHub issue #5517)

### Rebase continuation popup persists

If you complete a rebase externally (e.g., in another terminal), lazygit may still show the "continue rebase" popup. Press `<esc>` to dismiss it, or press `R` to refresh the state. (See GitHub issue #5197)

### Pull request integration shows 401 errors

If you use submodules with different GitHub credentials, the PR integration may fail with authentication errors. The PR fetch runs automatically and cannot currently be disabled via config. Ensure your GitHub credentials are configured correctly for all remotes. (See GitHub issue #5516)

### PR integration fails with URL casing mismatch

If your remote URL uses different casing than the GitHub repository (e.g., uppercase vs. lowercase letters in the owner or repo name), PR lookups may fail. Ensure your remote URL matches the exact casing on GitHub. (See GitHub issue #5494)

### Branch with empty name causes display issues

A branch with an empty name (which can be created through unusual git operations) may prevent the branch list from rendering correctly. Delete the problematic branch directly with `git branch -d ""` from the command line. (See GitHub issue #5112)

> [!CAUTION]
> Running `lazygit` inside a bare repository or a repository with a detached worktree requires explicit `--work-tree` and `--git-dir` flags. Without these, lazygit cannot locate your files.

### Debug mode

To diagnose issues, run lazygit with debug logging enabled:

```bash
lazygit --debug
```

Or set the environment variable:

```bash
DEBUG=TRUE lazygit
```

To tail the logs in real time (in a separate terminal):

```bash
lazygit --logs
```

You can customize the log path with:

```bash
LAZYGIT_LOG_PATH=/tmp/lazygit.log lazygit
```

Set the log level for more or less verbosity:

```bash
LOG_LEVEL=debug lazygit
```

### Performance issues

- **Large repositories:** Lazygit may feel sluggish in repos with thousands of changed files. Use path filtering (`lazygit --filter path/to/dir`) to limit scope.
- **Auto-fetch:** If network operations are slow, disable auto-fetch in config:

```yaml
git:
  autoFetch: false
```

- **Auto-refresh:** If you notice high CPU usage, check if your filesystem watcher is causing excessive refreshes. Press `R` to manually refresh instead of relying on auto-refresh.

---

## 7. FAQ

**Q: How do I quit lazygit?**
Press `q` to quit. If you want to quit and have your shell `cd` to the directory you were last browsing in lazygit, configure the `promptToReturnFromSubprocess` behavior. Press `Q` (shift) to quit without changing directory.

**Q: Can I use lazygit with a bare repository?**
Yes, but you must specify the work tree and git directory explicitly:

```bash
lazygit --work-tree=/path/to/worktree --git-dir=/path/to/repo.git
```

**Q: How do I customize keybindings?**
Add a `keybinding` section to your `config.yml`. See the Admin Guide for the full keybinding configuration reference.

**Q: Does lazygit support mouse input?**
Yes, mouse support is enabled by default. Click on panels, files, commits, and other elements to select them. Disable it with `gui.mouseEvents: false` in your config.

**Q: Can I open lazygit focused on a specific panel?**
Yes. Pass the panel name as a positional argument:

```bash
lazygit status    # Open focused on Status panel
lazygit branch    # Open focused on Branches panel
lazygit log       # Open focused on Commits panel
lazygit stash     # Open focused on Stash panel
```

**Q: How do I filter the git log to a specific file or directory?**
Use the `--filter` flag:

```bash
lazygit --filter src/main.go
```

Or press `<c-s>` inside lazygit to open the filtering menu.

**Q: Can I use multiple config files?**
Yes. Use the `--use-config-file` flag or `LG_CONFIG_FILE` environment variable with comma-separated paths:

```bash
lazygit --use-config-file base.yml,overrides.yml
```

Later files override earlier ones.

**Q: How do I configure lazygit to use delta / diff-so-fancy / difftastic as my pager?**
Set the pager in your config:

```yaml
# For delta
git:
  paging:
    colorArg: always
    pager: delta --dark --paging=never

# For diff-so-fancy
git:
  paging:
    colorArg: always
    pager: diff-so-fancy
```

**Q: What are the screen modes?**
Lazygit has three screen modes: **normal** (side panels + main view), **half** (enlarged main view), and **full** (main view only). Press `+` to cycle forward and `_` to cycle backward. You can also start in a specific mode:

```bash
lazygit --screen-mode full
```

**Q: Is there undo support?**
Yes. Press `z` to undo and `Z` to redo. This uses git's reflog to reverse operations like commits, checkouts, and rebases. Not all operations are undoable.

**Q: Can lazygit create GitHub pull requests?**
Yes. In the Branches panel, press `o` to create a pull request for the selected branch, `O` to view PR options, and `<c-y>` to copy the PR URL to your clipboard.

**Q: How do I open lazygit for a repo in a different directory?**
Use the `--path` flag:

```bash
lazygit --path /path/to/other/repo
```

**Q: What is the snake game?**
Lazygit includes a hidden snake game easter egg. It exists in the source code under `pkg/snake` but discovery is left as an exercise for the curious.

**Q: How do I change the interface language?**
Set `gui.language` in your config. Supported languages: `auto`, `en`, `zh-CN`, `zh-TW`, `pl`, `nl`, `ja`, `ko`, `ru`, `pt`.

---

_Generated May 2026 from jesseduffield/lazygit at d167063. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
