jesseduffield / lazygit

simple terminal UI for git commands
MIT License
53.12k stars 1.85k forks source link

What about adding a nice way to display a git commit graph? #2843

Open KarlHeitmann opened 1 year ago

KarlHeitmann commented 1 year ago

Topic There are no simple tools available to display a simple graph of commits. It should be easy, right? There are nice tools for VS Code (git graph) and other GUI. But what is out there for terminal?

Your thoughts

There is a nice project called git-igitt built on Rust. You can see a nice git graph displayed there. But it is not as feature and keybinding rich neither as simple as this project. git-igitt displays the git graph with aid of the git-graph Rust crate created by the same user. What is git-graph? it is a program that you can run on the terminal and will print a nice graph of git commits. It has many flags to switch different options (see the screenshots on the project to see what is all about).

Can we integrate this nice looking graph tool into the local branches panel? Or add a keybinding to switch from the current view to the git-graph view? Or add a new window to play with graph views?

The git-graph project uses lib2git to retrieve a walker that you can iterate and it will walk through the commits of the repository. You can add some globs to the walker to skip or start from some patterns (I have not studied enough how it works, otherwise I would have already solved the problem myself, lol :laughing: ). That's an idea if we want to build it from scratch. Other option is to add this git-graph binary to the project and spawn the process with the right arguments to draw what you want to draw. Another option (I think it is the most lame of all :laughing: ) is to do what I tried to do on my git_explorer project: fetch the commits one by one and following their parent by using its ID (HASH code),

Why I want this feature? Because commits on a git repository are nodes that are linked with each others. Why the existing tools are so lame to represent something that should be so simple to do? If you got a nice visual tool to show you dots and lines and carets you could see the git graph, go to a specific node and collapse and expand branches, by hitting enter on a commit that has 2 parents for example. This way you could see a git graph and just by hitting "enter" you would be collapsing complete branches until reaching the common ancestor that are adding noise to the graph (but this would be a future feature to add: collapse and expand branches on the git graph / node graph window).

This is related to another feature request I'd probably add on the issues page: a feature to fold/unfold branches. For example. If you've got many branches on your repository called:

bug/fix_typo_root_page bug/fix_broken_web_site bug/bla_bla_bla

The feature will fold these 3 branches into one:

bug/>

You can hit a special key to unfold the branches underneath your cursor (in this case, starting with bug) or to fold the branches that starts with the pattern of the branch underneath your cursor.

What do these features have in common? The possibility to collapse branches on the git graph and fold branches on the branches window: reduce the NOISE on the git repository. Too many branches that are not relevant to the work I'm currently doing. So there must be a way to hide what I am not interested in right now, instead of scrolling up and down on the git log.

I am willing to collaborate on this. Although you write Go and I write Rust, this is the best project I found on github up until now. The best "Code of conduct" :rofl: and nice tips on how to use VS Code. With the debugger set up and working and with good logs you are ready to do everything in no matter what language. I am already working on some good first issues :D

stefanhaller commented 1 year ago

Try opening your lazygit config file (by pressing 1 e) and adding

git:
  log:
    showGraph: always

I'd say this comes pretty close to the git-graph screenshot.

There's no collapsing and expanding, but I'm unsure how that would work, as the commit graph is not a tree where you could collapse entire subtrees as in a file browser.

stefanhaller commented 1 year ago

@KarlHeitmann I'm interested in your input on this. Did you try the git.log.showGraph option? How close does it come to satisfying your needs?

KarlHeitmann commented 1 year ago

Hey @stefanhaller !

Thanks for reaching out. I've tried it 3 weeks ago but didn't noticed anything different. Now I tried it again and saw a nice graph with some highlighted branches that changes as you go up and down through the Reflog window.

It is indeed pretty close to the git-graph screenshot... and it is better because it is interactive and it highlights the nodes from where the branch is coming. That's nice.

By the other hand, I was expecting this feature to be in the main Log window, the big window. This is because I don't know how to use git reflog. I remember when I first started using git I had to use it to recover a lost commit, and never used it again. Now I did a quick google search and found reflog stands for "Reference log" ('cos branches are references). But I am not familiar with the day to day use of git reflog (because I only used reflog to recover a lost commit, something that very strangely occurs (specially when you are learning git), but I've seen many experienced devs using git reflog, so I bet it has a cool feature I don't know it exists).

But the problem I'd like to solve it is to transform the branches into something like the subtrees in the file browser, so you can collapse/expand subtrees. I don't have many experience with the libgit2 API, neither have a deep understanding of it. AFAIS, there is no API option in libgit2 to collapse the subtrees, so it should be done from scratch. But it should be possible to do, because you can make a model of a git repo as a graph: nodes and vertices. You should be able to hide a sub set of nodes / sub set of graphs. Every commit is a node, and every parent-child relation is a vertices. One should be able to click a node with two parent, and hide all the ancestor until reaching the common grand-grand-parent again.

I will study more about git reflog, maybe the current feature satisfy my needs, but I'd have to learn reflog first in order to give you a definitive answer. But a priori, what I need is a way to collapse sub trees / sub graphs.

stefanhaller commented 1 year ago

Wow, big misconception here. None of this has anything to do with the reflog. I've seen this before, people read the panel title that says "Commits - Reflog" and think this is "the commits reflog". (Maybe it's more common for Germans because compound words are often written with a hyphen in German.) No, these are two different tabs, we're talking about the Commits tab here, the Reflog tab is totally unrelated.

About the main window: you can get somewhat close by setting the git.branchLogCmd config, e.g. to something like

git:
  branchLogCmd: git log --graph --color=always --abbrev-commit --oneline {{branchName}} --

It's not quite as nice as our own graph, but better than nothing, probably.

About collapsing/expanding: I'm not convinced it makes sense for the commit graph. For example, if you select a merge commit and collapse it, you might expect that this hides all the commits of the branch that was merged in that commit. However, it might hide a lot more commits than that, for example when people had merged master into their branch. I just don't think this can be made to work in a way people would expect it to, conceptually.

artemchistikovvokigamescom commented 11 months ago

Hey, @stefanhaller, I discovered lazygit a couple of days ago and think that its a killer app. It's lightning fast, easy to use and has a lot of cool features. But I do miss the expand/collapse merge commits also. Conceptually it works just fine on sublime merge and I have my merge commits collapsed almost always. We have around 200 contributors to our repository, about 50-100 commits daily and a lot of merge commits also. For example, I work on my feature and need to cherry-pick some commits from another branch as well as my own commits. At the same time I've merged our stable development branch into my branch. And now I can't get to see the commits I've cherry-picked because there is a merge commit which consists of 1000+ commits which I can't scroll because lazygit freezes forever 🤣 and neither can't collapse those merge commit.

stefanhaller commented 11 months ago

But I do miss the expand/collapse merge commits also. Conceptually it works just fine on sublime merge and I have my merge commits collapsed almost always.

OK, looking at Sublime Merge I see that it does make sense to collapse merge commits. Still, I wouldn't hold my breath that this gets added to lazygit soon, because it seems like a lot of complicated work to me given the way the commit graph is implemented (I'm happy to be proven wrong on that! 😄), and I personally have no interest in the feature, so I'm not planning to look into it myself.

The UX is also unclear to me, e.g. which keybindings to use for collapsing/expanding. In the Files panel we use enter for that, but that's already taken for checking out a detached head on that commit, so this needs some change. Maybe that's the smaller problem to solve though.

In the meantime, I'd recommend to mitigate the issue by caring about your commit history more. For example, avoid merging master into feature branches; rebase them onto master instead. I also find that it improves the graph a lot if you rebase a branch onto master again right before merging it back.

because there is a merge commit which consists of 1000+ commits

Yikes, that's what I meant. I'd just try to avoid that.

which I can't scroll because lazygit freezes forever 🤣

OK, now this is a separate problem, and work has been started to improve this (see #2533). I'm hoping to take that up again at some point.

artemchistikovvokigamescom commented 11 months ago

Hi, @stefanhaller, Thanks for your reply. Yesterday I've played a bit with it locally and managed to add a setting to collapse/expand all merge commits which is more than enough for me. Still have some issues with the graph being broken after toggling the setting. I've added a toggle setting to the "Commit Log Options" menu which basically collapses all the merge commits. Also I've added a possibility to set the value using the user config file. What do you think about this approach?

stefanhaller commented 11 months ago

That's interesting, I'd be curious to have a look, if you could push a branch somewhere to try out?

artemchistikovvokigamescom commented 11 months ago

Okay, I'll fix the bugs and push it.

driuba commented 8 months ago

Interestingly, I don't see the graph at all. The only difference git.log.showGraph makes is it shows circles next to commits. Screenshot from 2024-03-12 21-18-00

stefanhaller commented 8 months ago

Interestingly, I don't see the graph at all. The only difference git.log.showGraph makes is it shows circles next to commits.

That is the graph. It is usually a bit more interesting, but in this repo there is no branching going on, no merge commits, so it's just a straight line of commits. (Maybe you'd expect all those circles to be connected by a line, but there's not enough room in a terminal app to draw those.)

driuba commented 8 months ago

That is the graph. It is usually a bit more interesting, but in this repo there is no branching going on, no merge commits, so it's just a straight line of commits. (Maybe you'd expect all those circles to be connected by a line, but there's not enough room in a terminal app to draw those.)

I see. I was expecting to see all of the commits (similar to GitExtensions) in the commit pannel, not just the active branch. You are correct, in this case the graph is the line.

stefanhaller commented 8 months ago

I see. I was expecting to see all of the commits (similar to GitExtensions) in the commit pannel, not just the active branch.

That's a separate option; you can have that by typing ctrl-l to open the "View log options..." menu, and then choosing the "Toggle show whole git graph" option.

driuba commented 8 months ago

That's a separate option; you can have that by typing ctrl-l to open the "View log options..." menu, and then choosing the "Toggle show whole git graph" option.

For anyone else interested, this toggle can also be controlled with a flag in the config:

git:
  log:
    showWholeGraph: true
Kahitar commented 2 months ago

Reeeally miss this feature of collapsing merge commits... this is the one reason I still go back to sublime merge from time to time. It's just not practical to work with the commit history in a huge monorepo with 20 people working on it.

Although the rebase workflow is my personal favorite, unfortunately it's not feasable in a big'ish team...

Johnmcenroyy commented 1 month ago

There is also new interesting project Serie written in Rust. It is in official repo of Arch Linux.