Hacker News new | past | comments | ask | show | jobs | submit login
Lazygit: Simple terminal UI for Git commands (github.com/jesseduffield)
239 points by thunderbong on July 19, 2023 | hide | past | favorite | 79 comments



I found lazygit after building something of my own thay solves some of these problems for me - git-fuzzy [0].

I'd like to share some of my thoughts about the comparison.

lazygit is a TUI for git which can behave in a standalone fashion. It's also designed to be quick and easy to use to perform quite advanced actions but ones that a seasoned git user may really want when working with git history. Since I'm already a seasoned git user the main feature I like about lazygit is the ability to surgically work with patches.

All that said, a majority of my workflow is tightly bound to git-fuzzy. I use its CLI composability quite heavily in combination with aliases and functions - git-fuzzy excels in this particular way (`git fuzzy log $(git fuzzy branch)` which I invoke using `gl $(gb)` by way of aliases). git-fuzzy is better for working with git-log or git-reflog and interactively searching them.

I personally quite like what I made (for myself), though I wish there was a world where I could quickly and easily mash both of these projects together.

[0] https://github.com/bigH/git-fuzzy


Interesting project... in the hopes of maybe nerd-sniping you (or having someone tell me where it already exists), I'll tell you the story I'd really like a solution to but can never seem to find time to build:

I have 5 un-pushed commits. I missed a 1-line change to that first one. I add that one line change to staging (gitui/lazygit/whatever), then I want to `git commit --fixup=COMMIT`. Finding that COMMIT is always a manual process for me for two reasons.

First I have to find the commit to which it applies. This commit is almost always the commit that changed the same line, or added lines around it, or something similar. I guess you could say it's the commit with the closest proximity to the change I'm adding.

Second I have to find the hash of that commit. If I've since done something like an autosquash rebase then it'll have changed. I generally end up using the mouse to do a copy/paste at this point.

Why not skip the fixup commits and just rebase right then, you might ask. Well the commits are signed, and signing requires tapping my yubikey for each commit after that.

I would really like to be able to do something like `git commit --I'm-an-idiot-and-missed-this-so-please-apply-a-fixup-to-the-proper-commit`, and have it do the figuring out for me.


I usually solve this by commiting my fixup in a dummy commit, then do a rebase -i HEAD~n where n is the number of commits I want to look back at. Then during the rebase I just move my commit below the one that seem the most appropriate and mark it for squash. Execute the rebase. Done


If you have `fzf` installed you might try this alias.

    frbi = "!f() { git rebase -i $(git log --pretty=oneline --color=always | fzf --ansi | cut -d ' ' -f1)^ ; }; f"
I do: `git frbi` (which in my mind means Fzf ReBase Interactive)

Then I can easily scroll up to the commit I want to start the rebase on.


Wow, I never realized that changing the order of commits in an interactive rebase was a legit operation.

Thanks for the tip!


Another way to handle this if you haven't made the change yet is to do a `git rebase -i head~4` (or however far back) and mark the place where the change needs to happen as "edit". Make your change, add the file, then `git rebase --continue`.

If you've already made the change but haven't committed it, you can stash it before doing the rebase, then pop the stash while editing that commit.


Not as quick as you're asking for, but what I do, after running "git log" to jog my memory of what the commit message was, is this:

  git commit --fixup=':/message regexp'
This will find the youngest commit where the message matches the "message regexp" pattern. See also: https://git-scm.com/docs/gitrevisions


Boy have I got the thing for you. git absorb - https://github.com/tummychow/git-absorb

The way to work with it is:

    git add file1
    git commit -m "Fix some bug in file1"
    git add file2
    git commit -m "Add a feature flag for file1"
    # Oh no, first commit was borked, need to fix it
    git add file1
    git absorb
    # this will now automatically create one or more fixup commits
    git rebase -i --autosquash $(git merge-base master)
    # voila, tidy history and each commit works


This was my bugbear for a long time too, and then I found fzf-git.sh (actually its PowerShell equivalent, PSFzf).

fzf (absolutely incredible tool with many uses) gives you fuzzy searching of anything you care to name, and fzf-git combines this with shell key bindings to let you pop up a fuzzy-searchable list of branches/commits/tags/whatever while typing your fixup command, then paste the object you select into your in-progress command line.

No more counting commits in log output to know how many ^ to put after HEAD, or copying out segments of commit SHAs!


https://github.com/tummychow/git-absorb Does a very nice job of this for me.


>> git absorb will automatically identify which commits are safe to modify, and which staged changes belong to each of those commits. It will then write fixup! commits for each of those changes.

This looks like exactly what I wanted. Thank you!


Lazygit allows you to easily « add » your stated changes to any commit (doing a rebase under the hood). Stage stuff, find the commit (the UI helps to quickly find the right commit) and press « a » for amend.

It’s not quite as automatic as you describe, but it’s super quick if you vaguely know what commit you want to amend and there’s no magic happening: just a good ui


Ty. I've seen similar in other tools, and I agree that it's super quick... unless you sign your commits with a key that requires a physical touch of a yubikey. Then it's <tap> <wait> <tap> <wait> for every commit that comes after the one you just modified.


I do this a lot in lazygit, or at least something that sounds similar: I’ve got some changes, I stage them by pressing spacebar (or hitting enter and adding lines in a more granular way), and then switch to the Commits tab, arrow down to the one I want to add this change to (all the unpushed ones are red) and hit A to amend.


I can’t solve the whole problem for you, but you can `git commit --fixup HEAD~4` if you know it’s 5 commits back. No need to figure out the hash. `HEAD^^^^` would also work — sometimes if I have to repeatedly fixup the same commit, adding an additional ^ to a previous command is easiest.


Lazygit maintainer here: I've found myself in your shoes quite a bit (without the commit signing part) and a few weeks ago I put up a draft PR where if a file is selected, it highlights the commits that touch that file. Typically you want to amend the most recent commit that changed the file and typically that commit is visible without needing to scroll. But I haven't spent much time thinking about what the ideal UX is, how to activate it, etc.

PR: https://github.com/jesseduffield/lazygit/pull/2654


I want this too. We just shipped "amend from status" allowing you to push staged files into the HEAD commit. It's only a small step to add selection of the commit to amend.

Feel free to make a PR. If not, I'll probably queue it up to work on at some point.


Of tools that mash interactive GUIs (lazygit) with scriptable shells (git fuzzy), I only know of AutoCAD. Scripts would routinely ask you to interactively select a set of points or an item in a list.

Are there other apps that offer scriptable GUIs ?


Emacs (which, incidentally, uses a lisp for scripting, like autocad).


> Are there other apps that offer scriptable GUIs

Isn't this the essence of "plugins" in most GUI apps?


I vaguely remember doing similar things with Matlab, but it has been a while and I don't recollect fully.


thanks for this. I love the _idea_ of lazygit but I've never managed to work it into my workflow. git-fuzzy looks _much_ more inline with something that I'd be likely to keep using and I'm definitely going to give it a shot. I've got something similar for fuzzy picking branches and it's been great.


I'm using this tool for a couple of months now and I fully enjoy it. I was always the CLI type when it comes to using git. I never liked the ambiguity that regular UI tools introduced. I want to know which git commands are being executed when I click a button or drag and drop a commit.

With lazygit, I never missed that feeling of control. All commands are printed and rather complicated rebases become a breeze. Highly appreciate this tool! :)


Looks rather nice when looking at, but I have to say that (for me) the animations in the github page are way to fast to get any feeling of what the tool does.


This YouTube video is linked from the README: https://www.youtube.com/watch?v=CPLdltN7wgE


I use IntelliJ IDEA and often rely on their own Git functionality. But it cannot stage specific lines, only whole chunks [1]. For that, I've been using lazygit for a couple of months now. I like its simple UI and that it makes staging specific lines very easy and quick. If you like lazygit, you might also be interested in similar Git CLI clients that I collected here [2].

[1] https://youtrack.jetbrains.com/issue/IDEA-186988/Allow-commi...

[2] https://github.com/frontaid/git-cli-tools#clients


Unless I'm misunderstanding your comment, this feature is actually included in the latest EAP/beta releases[1]. There is discussion of it at the bottom of the issue you linked.

[1] https://blog.jetbrains.com/idea/2023/06/intellij-idea-2023-2...


Yes, that's it. Judging from the screencast, I will continue using lazygit for that though. Not a fan of all the clicking. Hopefully there will be a keystroke available for it.


Is this something missing specifically from IDEA?

In Rider, there are features that allow committing individual lines instead of a whole file. You can select in the commit dialog which lines to include/omit. Also I recommended taking a look at Changelists feature that allows separating certain changes from what would be committed next (I believe it works line by line basis).


I don't know Rider, but I assume this is a limitation in all of their IDEs. Yes, you can commit only certain changes within a file. But you can only do that based on whole chunks. For example, if you add two new lines at the end of an existing file, you cannot commit only one line but not the other. The same limitation applies to changelists (at least in IntelliJ IDEA and Webstorm).


Doesn't this come from git itself? If you try `git add -p <file>`, it'll chunk just as "bad".


Yes, git generally stages just hunks with the patch add mechanism, but it is possible to stage single lines, but it is a bit tedious, see: https://kennyballou.com/blog/2015/10/art-manually-edit-hunks...


You can edit the hunk manually. I believe it's also possible to construct a hunk to apply entirely from scratch as long as you get the header right.


Indeed. That is a limitation with Rider too.


FWIW, the per line staging functionality in GitUp (https://gitup.co/) is quite easy and straightforward. Very lightweight program that you can open via cli (`gitup` when in a git directory)


MacOS only


Wow. VS Code can do that.


It's nice but I prefer https://github.com/extrawurst/gitui cause it's a little snappier.


Of course it’s written in rust


I'm curious how much people prefer TUIs over editor-plugin-GUIs these days. I'm getting more and more persuaded by the plugin model personally - perhaps partly by how easy it is to discover, install, update, uninstall, etc VSCode plugins


I prefer it, but I also prefer to stick to the terminal as much as possible. If I were a VSCode user, I might disagree.

My main factor is I don't want to have to context switch across applications. I don't feel like I'm doing that if I stay in the terminal. As such, I would imagine if I were a VSCode user, I'd prefer a git plugin there.

VCS is very much tied to the code, so I think it makes sense to co-locate.


Recently for conflict resolving i will open up vs code. I find it so much more reliable and convenient there. I can quickly see the conflicts resolve then stage. But when it comes to more detailed things nothing compares to the cli.

There is a small learning curve for the commands but it's minor compared to the intuitive control you get. A lot of the dedicated tools are just too bloated and use different terminology than the git standard which baffles me.

My colleague will use source tree and Everytime I see him doing stuff I always think : "But that's not what the got command is called for that".


I don't know if it's a "I want a TUI rather than a plug-in" vibe. For me, it's more of a "it fits my workflow".

I use helix as an editor and like to use a range of command line tools and scripts for regular stuff. Lazygit fits right into that and I don't have to leave the terminal.

I used vs-code a few years ago and its got plugin was (I assume still is) pretty good, if I used it as my editor then I'd probably use a plug in like you say, but as things are lazygit is both an awesome tool and the path of least resistance.


The state of desktop application is pretty alarming, everything is its own web browser..

I'm glad people still build these TUIs, that's exactly what i need, simple interaction with my keyboard, no fuss, no bloat (edit: just checked, the executable is pretty large ~5mb, I wish Go made some effort in that area), a simple executable that can run on my headless server through SSH


Emacs has had this forever...


The built in support for git in Visual Studio 2022 is pretty good, but I do occasionally find myself reaching for the command line still.


Jetbrains has this down so well. I sometimes wish I could open up a light weight version of their IDE just for git management.


I love this app, use it every day. Very seldom do I need to drop out of it to run a specific command (and even then it’s probably capable of doing it and I’ve just not bothered to figure out how).


There used to be GitX for macOS, which was a very nice, lightweight GUI tool. Sadly it is no longer maintained. There are a few forks though, but they all seem to hang or crash in their own unique way making them unusable for me.

Lazygit for me brings over the feature that made GitX the greatest and that was the way it allowed to quickly and easily select a few lines of changes from each file and add them to the index for commit or amend them to a different commit. Lazygit even ramps this up with a lot of nice tooling around interactive rebase (like reordering, editing commits directly, squasing, deleting commits, reword, etc) which makes it a feast instead of a file editing/context juggling chore.


I've used this before and it is great. I mainly use Sublime Merge these days, though: https://www.sublimemerge.com/


Can also vouch for Sublime Merge, I use it for managing commits (especially staging hunks without having to stash edit pop if I have multiple ongoing changes). I still use git at the CLI for pulls etc.


Is it possible to move a commit up/down by 10 lines instead of 1?


How does this stack up against tig?

https://jonas.github.io/tig


tig is great for a read only operations. Looking at the tree, peeking at diffs, finding specific commits. It's quicker to get in and out of. I reach for it instead of `git log`.

lazygit makes it super easy to make modifications. Reorder commits, revert specific hunks from commits. I find it easier to use if I need to look at a really big diff. I reach for it instead of `git rebase -i`, and it can do things no native tool can do easily (such as revert or extract specific hunks from commit earlier in the tree.

I use both multiple times per day. tig if I just want to look at stuff (fewer keystrokes to look at diffs in the tui!) and lazygit if I want to modify stuff (more powerful!).


I find marking files, hunks and single lines to commit extremely comfortable in tig. And also reverting is as easy as selecting a file or hunk and pressing Shift+1. But yes, more complex operations are not supported or rather you have to define an external command and thus use an external tool for those.


See https://github.com/Extrawurst/gitui#3--benchmarks-top- for a comparison on indexing the linux kernel


Maintainer here, thanks for the shoutout!

A new version just came out today https://github.com/jesseduffield/lazygit/releases/tag/v0.39....

In the next release we're adding worktree support: if you use worktrees in your daily flow I'd love to know what that flow looks like and what your pain points are so feel free to join the discussion here: https://github.com/jesseduffield/lazygit/discussions/2803


I have been using lazygit for years. Love this tool. It is fast, doesn't need much ram, I don't have to leave my terminal (I also use byobu / tmux for tabs). I also use lazydocker from the same developer.


I've been using this a for while now as a replacement for fugitive, since moving from Neovim to Helix. Overall it's great, but I do wish there were some better tutorials for it thou.


Thanks for the feedback, I've been slack on documentation as more features have been added. Do you have a preference for tutorials? e.g. video or text?


Did you check their Wiki? Have a nice set of gifs


I use lazygit extensively. Have an zsh alias 'lg' for it.


So, its not just me!


I use this a lot, as well as Magit. Simple terminal commands work fine, but I like selecting what chunks of code I want to commit, and these tools make it especially easy.


My only gripe with Magit (I'm not sure how Lazygit does with this) is how hard it is to search a large commit log. l l will pull up a truncated list of commits that you can search in, but if the commit you want isn't in that list, you have to keep requesting a handful more commits at a time to search in. I find it can be faster to just use git log and search in my pager instead.

Otherwise Magit is a fantastic piece of software :D


When you have the magit log transient menu open, press `-n` to disable the limit on the number of commits. You can reconfigure this to be the default if you want, or you could extend the default limit beyond 256.


I love lazygit, until I start typing a commit message only to find that I hadn't selected any files, and lazygit has processed each key-press as a command, and my repo is some bizarre state :)

But anyway, I typically have it sitting quietly in a terminal pane and just use it for selecting files/hunks/lines for easy commit message editing. It's great for that.


Maybe some VSCode users can tell me what specific actions Lazygit do that Gitlens (free version), can't do? And gitlens can do a lot (stash handling, commit revert, branch checkout from remote, autofetch, rebase and many more). Or is it just a different workflow that others find easy to use?


I use VSCode but not git lens. I don't think it does much that Lens doesn't, it's indeed a different workflow for me: I don't like to use the mouse so the clicky-clicky workflow of Lens doesn't work for me, I'm much faster with lazygit (and I can instantly drop to the `git` CLI if there's something I don't know how to do with lazygit, as I'm already in the terminal).

I'm not particularly keen to have my VCS and my code editing in the same software really, although I wouldn't say that it's a superior approach.


> I'm not particularly keen to have my VCS and my code editing in the same software really, although I wouldn't say that it's a superior approach.

Addendum: I'm also not always using VSCode. Sometimes I just use vim if I'm already in my terminal and it's a small edit, at which point I don't want to have to go back to VSCode (potentially having to open the project) just for git


I thought I was a weirdo for splitting my usage between VSCode and nvim. I do the same! And I don't even use any fancy vim features. I think it's a mental separation for me: "right now, I am doing sysadmin stuff and need to have my sysadmin brain on" vs "right now, I am developing software and need to have my software brain on", but I'm not even really sure about that.


My workflow is similar. For one larger project, I am just more comfortable operating in VSCode, but if I need to work in a smaller project, I tend to just fire up NeoVim, and I've found the transition to Lazygit to be fairly smooth.


My personal take: I like using the keyboard. Lazygit works very smoothly with the keyboard, of course.

I tried the git thing that’s part of vscode and it really wants me to click. It is theoretically possible to get by without, but it’s cumbersome.


Thanks that makes sense especially for folks that use keyboard and like to do it within CLI.


So how do I discover a command? In a GUI client you'd have a menu, a search through menu, and a command palette with fuzzy search, then also more context-sensitive mouse context menu


Just type "?" And it brings up all commands in a given window


So do you scroll through the whole list to find what you want?


why not just git cli?


[flagged]


This might be helpful when creating lists of things on HN:

https://news.ycombinator.com/formatdoc

"Blank lines separate paragraphs."




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: