# Enhancements over lazygit

Ziggity follows lazygit's workflow, and in a number of places it deliberately
diverges to behave better. The full write up, with measurements and animated
demos, lives in [comparison.md](comparison.md). This page stays as the short
form index of those intentional differences.

## The list, in short

- **Small and fast.** A 1.9 MB static binary against 17.6 MB, one linked
  dynamic library against four, about 4 ms of process startup against about
  21 ms, 16 git subprocesses to load a repo against 25, 8 MB resident once
  settled against 36 MB, and about two thirds of the total CPU over a ten
  second window (a sixth of it in its own process), measured on the same
  machine and repository with [`docs/bench`](bench/). Eleven panel loaders fan
  out in parallel, the log loads incrementally, previews are cached, and
  loading never touches the network. Memory stays flat from launch, with the
  peak while loading no higher than the settled figure.
  [Details](comparison.md#small-and-fast)

- **Nothing blocks, ever.** Fetch, pull, push and slow multistep actions run
  off the interface thread with a spinner while navigation stays live.
  Success is silent, only failures open a dialog, and you are never dropped
  back to the raw terminal with a "press enter to return" screen.
  [Details](comparison.md#nothing-blocks-ever)

- **Credential entry in the app.** On an HTTPS auth failure Ziggity prompts
  for username and token in a popup and feeds git through an askpass reexec
  of its own binary. No PTY tricks, no terminal corruption, no environment
  races; keychain helpers still cache the result, entered credentials are
  authoritative over stale cached ones, secrets are wiped after use, and a
  host that wants a token instead of a password gets said out loud.
  [Details](comparison.md#nothing-blocks-ever)

- **Mouse text selection with automatic copy.** Character precise click and
  drag selection in the Diff panel and in the read only dialogs (command
  output, help overlay, command log). On release the text is on the
  clipboard via OSC 52, color codes stripped, indentation preserved.
  lazygit has no in-app selection; you fall back to the terminal's own,
  which grabs panel borders too.
  [Details](comparison.md#copy-text-straight-from-the-screen)

- **The mouse works everywhere.** Click to focus a panel, click to select a
  row, click a line in the staging view to land the cursor on it, click a
  completion in the checkout prompt, wheel scroll every list, dialog and the
  graph.
  [Details](comparison.md#the-mouse-works-everywhere)

- **At home in any terminal.** Standard ANSI plus a curated 256 color set,
  emphasis through dim and bold, OSC 52 copy that survives SSH, focus
  events, bracketed paste, and the kitty keyboard protocol where available.
  [Details](comparison.md#at-home-in-any-terminal)

- **Checkout by name that lands on a real branch.** In the `c` prompt a
  remote branch name checks out with `--track`: a local tracking branch, in
  one step, never a detached HEAD and no extra menu. An existing local name
  switches, a tag or commit detaches because that is the only correct
  meaning.
  [Details](comparison.md#checkout-by-name-that-lands-on-a-real-branch)

- **A commit editor that nudges the 50/72 rule.** A live subject counter
  that turns red past 50 and a soft guide column at 72 in the body, both
  configurable.
  [Details](comparison.md#a-commit-editor-that-nudges-the-5072-rule)

- **prepare-commit-msg hook seeding.** The dialog runs the hook the way an
  interactive commit would (empty source argument), so branch ticket prefix
  hooks finally fire from a TUI. Addresses lazygit issue
  [#4995](https://github.com/jesseduffield/lazygit/issues/4995).
  [Details](comparison.md#a-commit-editor-that-nudges-the-5072-rule)

- **An escalating force push chain with no dead ends.** Rejected push, then
  confirmed `--force-with-lease`, then confirmed `--force`, then stop. The
  safe force always comes first and the path never depends on whether the
  remote tracking ref happens to be stored locally.
  [Details](comparison.md#a-force-push-that-never-dead-ends)

- **A diffing mode you can read off the screen.** One `W` marks the selected
  ref as the base (no menu detour), a note explains the mode, the marked row
  keeps a colored diamond, and the Diff title tracks every selection in
  git's own notation with the real ref names (`main...feature/login`): order
  is direction, dot count is mode. lazygit's diffing opens a menu first and
  shows no marker and no comparison state.
  [Details](comparison.md#diffs-the-way-review-tools-show-them)

- **Merge base (three dot) diffing, on by default for branches.** Diffing
  mode can show `git diff base...target`, only the target's own changes
  since divergence, the pull request view; it is the default whenever the
  marked base is a branch, while commits and tags default to the plain two
  dot comparison. Composes with the invert toggle. Addresses lazygit issue
  [#3767](https://github.com/jesseduffield/lazygit/issues/3767), still open
  there.
  [Details](comparison.md#diffs-the-way-review-tools-show-them)

- **Word-level diff highlighting.** Within a changed `-`/`+` line pair, the
  words that actually differ get a stronger background (dark red behind removed,
  dark green behind added), delta and GitHub style, so a one-token change does
  not read as two fully repainted lines. The two-line layout is kept. lazygit
  colors whole lines only. On by default (`highlight_word_diff`); the two
  backgrounds are themeable (`word_add_bg`, `word_del_bg`).
  [Details](comparison.md#word-level-diff-highlighting)

- **Soft-wrap long lines in every diff panel.** `ctrl+w` wraps long diff lines
  to the view width instead of truncating them, so a prose/markdown paragraph
  and the change inside it stay visible without sideways scrolling; the word
  highlight travels onto the wrapped rows, aligned through wide chars, emoji and
  tabs. lazygit wraps its staging view only (`wrapLinesInStagingView`); Ziggity
  covers the preview, staging and fullscreen behind one session-wide toggle,
  starting off and defaulting on with `wrap_diff = true`.
  [Details](comparison.md#wrap-long-lines-on-demand)

- **First parent navigation in the commit graph.** `p` jumps to the current
  commit's first parent via a preloaded parent map, so walking the mainline
  of a merge heavy history is instant. Addresses lazygit issue
  [#3974](https://github.com/jesseduffield/lazygit/issues/3974).
  [Details](comparison.md#history-navigation-with-intent)

- **Reset from the commit graph.** `space` on a graph row resets the current
  branch to that commit (soft / mixed / hard), so you can spot the last merge
  in the DAG and rewind straight to it. The hint appears only for a commit on
  the current branch, the sole valid `git reset` target.

- **Discard-all lists every file first.** The `D` confirmation shows the full
  set of files it will wipe (staged, unstaged and untracked), scrollable with
  `j`/`k` and the wheel when the list is long and pannable with `H`/`L` when a
  path is wider than the popup, so a change hidden below a short Files panel
  can't be discarded unseen. lazygit's prompt caps the preview at the first
  three paths plus a "and N more" summary. The single-file discard menu (`d`)
  likewise names its target file (or folder) and carries the same yellow
  warning above the choices.

- **A Divergence tab and push state everywhere.** The current branch versus
  its upstream, outgoing above incoming, with history editing keys disabled
  there; commit hashes are tinted red until they reach the remote. The
  commit graph shows the upstream by default so incoming commits are visible
  without asking.
  [Details](comparison.md#history-navigation-with-intent)

- **Independent Branches and Commits drill downs.** Both panels keep their
  own selection and file lists at the same time, so inspecting another
  branch never loses your place in the main log, and diffing mode targets
  the drilled commit you are actually on.
  [Details](comparison.md#two-histories-side-by-side)

- **Stash without losing your working tree.** Snapshot everything into a
  stash, untracked files included, while the tree stays untouched. Git's own
  `stash create` silently ignores untracked files; ziggity stashes with
  `--include-untracked` and reapplies with `--index`, so the entry is
  complete and the staged and unstaged split survives byte for byte.
  [Details](comparison.md#stash-without-losing-your-working-tree)

- **Pull request status for GitHub and GitLab.** Each local branch shows its
  PR/MR as a state coloured `#<number> - <State>`, fetched in the background via
  the host CLI (`gh` or `glab`), and `G` opens the branch's own PR when it has
  one.
  Lazygit shows this only for GitHub via `gh`; ziggity adds GitLab via `glab`
  on the same mechanism, with no extra token handling.

- **Small courtesies.** One remote skips the remote prompt on tag push. Any
  stash exports to a `git apply` ready patch. A commit with thousands of
  binary files previews instantly instead of freezing the panel. `ctrl+z`
  undoes the last operation through the reflog.
  [Details](comparison.md#small-courtesies)
