Lazygit: The Intuitive Git UI That Will Transform Your Workflow
Uncover `lazygit`, the terminal UI that transformed one developer's Git workflow. This post highlights its superior UX, consistency, and interactivity for enhanced productivity.
During paternity leave last April, I embarked on ambitious learning plans, primarily to master Neovim for coding. As a dedicated Goland user, I've always been drawn to no-mouse, open-source setups, powered by gopls and highly configurable.
While I'll likely stick with Goland for professional work, my experiments with nvim led to an accidental discovery: lazygit Git UI. A simple mistype of <space>gg instead of gg revealed its built-in overlay UI. Within a week, lazygit had replaced all my Git workflows, both inside and outside nvim.
This post explores why lazygit quickly became indispensable, how it boosts productivity, and what lessons it offers for designing exceptional software with seamless user experience.
Let's dive in!
A "Lazy" Approach to Git Tools
Most developers are familiar with and use the git CLI. It's straightforward and incredibly stable; the most significant change in a decade was the introduction of git switch, though many (myself included) still prefer git checkout.
Consequently, developers often memorize a few core commands (e.g., clone, fetch/pull, config/remote, add/rm, status, checkout, commit, push, cherry-pick, rebase, merge, log) and stick to the CLI. A 2022 StackOverflow survey reported that 83% of respondents preferred CLI interfaces, a number likely still high today.
However, graphical interfaces and other Git-compatible clients do exist:
- Some offer similar Git workflows to the CLI but with visual appeal and interactive buttons, such as
git gui,GitHub Desktop, or lazygit itself. - Others, like
GitKraken, introduce additional features (e.g., AI) and new abstractions to simplify or enhance Git usage. - Projects like the popular
jjtool go further, completely abstracting away the Git API and replacing it with new source control flows to unify across various VCS (e.g., Mercurial, Google Piper).
The choice of tool depends on your preferences, workflow, and project type (monorepo vs. small repos, open vs. closed source, GitHub vs. other hosting). However, it's crucial for new software engineers to learn the git CLI first. It provides fundamental understanding and is indispensable for debugging environments without UI access, such as CI systems. As the official Git documentation states, "the command-line is still where you’ll have the most power and control when working with your repositories."
Personally, I need tools that are:
- Simple and fast, to minimize context-switching overhead.
- Git CLI-native, reducing potential issues.
- "Discoverable" and interactive, as my memory isn't geared towards keybindings and commands.
Early in my career, I adopted a hybrid workflow, using git gui for status, commit, config/remote, add/rm, and push, and gitk for log. The CLI handled everything else. I used these tools continuously for a decade.
Years ago, their outdated appearance and lack of modern features prompted me to seek alternatives. A frustrating experience of accidentally losing local changes in a GUI tool made me skeptical of finding a worthy replacement. The arguments for a switch had to be compelling.
It turns out, an open mind and a dash of curiosity led to a breakthrough. I stumbled upon lazygit, and after a brief trial, it quickly became my primary Git tool.
What Makes lazygit So Special?
lazygit addressed so many of my needs:
- It's incredibly easy to use, making you productive from day one.
- It empowers you to do more, faster, and even teaches you along the way.
- As a TUI (terminal user interface), it's exceptionally fast, portable, and visually consistent.
Many of its benefits also offer valuable lessons for building brilliant developer tools and software in general.
lazygit used via its IntelliJ plugin on a Git clone of the Prometheus project.
The best aspect of lazygit is arguably its user experience, specifically how easily it can be adopted with just a basic understanding of the git CLI. This superior UX is achieved through deliberate choices in consistency, clear visualizations, and interactive menus.
Consistency
lazygit is remarkably well-organized and visually consistent. Its TUI features a set of "views" (boxes) that maintain consistent behavior. Most views are generally visible, regardless of the operation, with a clear focus on one box at a time. Boxes on the left often drive changes in the right-hand panel.
Crucially, lazygit adheres to native Git terms and abstractions, significantly reducing the initial learning curve. It even introduces users to more advanced Git operations (e.g., bisect, which I used to perform manually) and terms (e.g., I learned that "hunk" is an official Git term for a piece of relevant code).
Furthermore, lazygit defaults to vim-like keybindings and feel: q quits, h/j/k/l (or arrows) navigate, / filters, and y copies. Commands often align with their first letter: c commits, a adds all, A amends, f fetches, p pulls, P pushes, r rebases. This consistency allows common workflows to be easily memorized and executed with minimal keystrokes.
While highly efficient, this vim-like approach can be a double-edged sword for those whose brains (like mine) struggle with remembering specific keybindings. lazygit mitigates this with a limited command set (adhering to the "do one thing and do it well" philosophy) and excellent "discoverability."
Discoverability
lazygit masterfully balances showing essential data only when needed. Upon opening the tool, it anticipates your need for Git operations and provides a concise overview:
- The current repository.
- All staged and unstaged files with changes (analogous to
git status). - Your current branch.
- The top ~10 commits on the branch.
- The top stash item.
- Recently performed Git commands.
- Core actions and their associated keybindings.
This wealth of information is presented without overwhelming the user:
Consistent and self-explanatory views with a flat action menu allow you to find the data you need quickly.
This immediate context is transformative:
- Whether you're a new user or returning to coding after a break, you instantly understand your current state and where everything is.
- It reduces surprises and mistakes (e.g., "Oops! I pushed directly to main!"), saving significant software engineering hours monthly.
- Traditionally, verifying this information would require multiple commands and checking different windows.
lazygiteliminates this context switching. - Even if you forget keybindings, they're easily accessible in the footer or by pressing
?.
Beyond discoverability, lazygit guides you through operations with impressive interactivity.
Interactivity
Unlike many UI tools cluttered with buttons and nested menus, lazygit teaches you what's possible and when. For instance:
- Initiating a push will warn you of divergence with the upstream if detected. Pressing
Enterwill execute a--forcepush, whileEsccancels. - A rebase operation will prompt you to choose between interactive or non-interactive, and double-check the target branch.
Interactive rebase in
lazygit is far more guided and intuitive than git rebase --interactive. There's no need to manually type and remember specific commands like pick/drop/squash (or p/d/s). The <c-j> and <c-k> keys quickly reorder commits.
Git conflicts after a rebase are highlighted. Once resolved,
lazygit automatically prompts you to commit the changes and continue the rebase.
- When switching branches with conflicting changes,
lazygitautomatically asks if you want to auto-stash those changes.
In essence, lazygit streamlines your workflows with minimal distractions and guesswork, quickly building trust and enabling faster adoption of efficient practices.
Enhanced Git Workflows
lazygit has significantly boosted my Git workflow productivity, a sentiment shared by many other satisfied users. What's remarkable is that it achieves this not by introducing entirely new workflows, but by making existing git CLI operations more usable, safer, quicker, and discoverable. It subtly teaches better patterns.
A prime example is custom patching. Imagine you've committed changes but later need to revert just a few specific lines from an earlier commit. My previous workflow involved either:
- Using local IDE history (often slow, too granular, and not always available).
- In
git gui, clicking "amend" to pull all changed files into the staged area, then manually copying the desired lines (including Git diff+and-characters!) and pasting them into the IDE, followed by trimming unwanted characters. A rather cumbersome habit.
With lazygit, I initially tried to replicate my inefficient workflow. I couldn't, as lazygit's diffs aren't intuitively selectable for copy-pasting (though this is a known feature request). I even upvoted an issue about it, and I'm glad I did, as the maintainer pointed me to a 10x simpler workflow: native reset/patch per line/hunk!
All Git diffs in
lazygit (whether unstaged, staged, stashed, or committed changes) support per-line or hunk selection and patching/selection.
This feature transformed my "line reset from the last commit" workflow, making it:
- Simpler.
- Contained within a single tool.
- Applicable to any commit, not just the latest.
Steps in lazygit:
Focus on commits view > select commit > select file > select lines to reset > patch options > "remove patch from the original commit." This can be done either mouse-assisted or with a quick 4 enter enter space
These short keybindings are generally game-changers. I recommend starting with a slower, mouse-assisted flow, and you'll naturally memorize the necessary keystrokes. For me, after some time, these quick flows became unconscious habits.
As a result, my common Git flows with lazygit were significantly improved:
-
Iterating on changes and updating upstream (ensuring a clean commit log):
select files to commit > add to the last commit (amend) > force push(2 space A P enter) -
Iterating on changes and updating upstream with a new commit:
select files to commit > create new commit > push(2 space cP ) -
Syncing branches (I generally prefer interactive rebase over merges, unless squashed):
select branch > rebase > interactive rebase > arrange commits > rebase options > continue(3 r i <s/p/d/.. to arrange rebase> m c) -
Removing an unwanted commit from history: Normally, this requires a full interactive rebase against
HEAD~4or similar, but now:select commit > drop(4 d) -
Removing unwanted file changes from commits:
select commit > select file > remove(4 enter d) -
Splitting a commit into multiple PRs/commits (normally a painful process):
select commit > select file > select lines or hunks > patch options > move patch into new commit after the original commit > create new commit(4 enter entern )enter
- Cherry-pick (typically prone to errors due to copying commit SHAs):
select branch > select commit > copy for cherry-pick (you can buffer many) > select target branch > go to commits > paste(3 4 C 3 4 V)
...and many more!
What Can We Learn?
lazygit isn't just a fantastic daily tool; it's an inspiration for devtools UX. Its simplicity, consistency, discoverability, sane defaults, shortcuts for common flows, and interactivity should be priorities for anyone building developer tools. This is coupled with deep configurability, healthy extensibility, being fully free (donations welcome!), a thriving OSS situation, and being 100% written in Go!
Imagine the other tools we could create by reusing similar patterns or even the same UX! The TUI framework and lazygit code are fully OSS (MIT licensed), providing a robust foundation for new tools. I have several ideas, especially for complex manual release workflows in our ecosystem. Let's collaborate! 💪
Summary
I hope this write-up was helpful. Even with advancements in GenAI, the statistical nature of LLMs makes them unsuitable for reliable and accurate version control changes crucial for projects. While LLM assistance (e.g., generating commit messages) will likely integrate into lazygit and other Git tooling, the core of lazygit will remain incredibly relevant for increasingly AI-assisted software development cycles.
Kudos to all maintainers, contributors, and sponsors of lazygit for their amazing work! Feel free to comment, give feedback, and contribute to the lazygit project. Happy coding!
Updated on 2025-11-10
Related: Optimizing in-process gRPC with Go 1.23 Iterators and Coroutines
Comments: 👋 Want to give feedback or ask questions? DM/email me or create a GitHub issue here via "New Issue"