Show HN: ggc – A terminal-based Git CLI written in Go
github.comHi HN,
I built ggc (https://github.com/bmf-san/ggc), a terminal-based Git CLI tool written in Go.
ggc provides: - A fast interactive UI (like `fzf`) for common Git operations
- Traditional subcommands (e.g. `ggc add`, `ggc commit`)
- Git-compatible config support (`ggc config` reads from `git config`)
- Built-in aliases and workflow automation (e.g. `ggc addcommitpush`)
The goal is to improve developer productivity by combining interactive workflows with scriptable CLI operations.
It's still under active development, but I'd love feedback from the community!
GitHub: https://github.com/bmf-san/ggc Demo GIF: https://github.com/bmf-san/ggc#demo
Thanks!
The display weirdness (e.g. the Z shell's percent character showing up) that you are seeing in your demo is because you are putting the terminal line discipline into raw mode, raw mode of course does not do CR-before-LF stuffing, and there's some confusion in the code as to when it does and when it does not explicitly emit CRs.
* https://github.com/bmf-san/ggc/blob/9e93ef8a87973cab916e37a9...
* https://github.com/bmf-san/ggc/blob/9e93ef8a87973cab916e37a9...
Where is the "%" showing up? I only see it before he runs ggc. It is common to use "%" instead of "$" in some shells.
In particular, C Shell (csh) and Tcsh uses "%" as the prompt character. Common in BSD systems.
Of course you can customize Zsh (or Bash) to show "%", too.
Edit: never mind, I noticed it when he quit "ggc". My bad. :)
This is not intended to be an insult of any sort, but I am pretty sure the use of LLM to write this was not so moderate, but I have nothing against it, you have a working project. I have done the same with projects similar to this.
I use lazygit (also written in Go) and magit a lot, they are quite nice. For GUI, I use Git Cola.
I wish the demo GIF was something more complex, perhaps adding & removing a particular chunk and committing it or something like that.
I loved using Magit. It’s awesome.
But these days, I’ve moved on to jujutsu, a git-compatible version control system with much better primitives than git.
If you haven’t tried jj, I highly recommend it. The first-class conflicts and powerful but simple primitives for editing the commit graph are amazing.
It makes stacking branches an absolute breeze compared to git. And since it is git compatible nobody on your team has to change how they work.
Yep. Having made the switch, I now see git (as a user-facing VCS) as a dead end.
It’ll take awhile for people to switch, but I think it will happen eventually. Invisible git compatibility means we don’t have to get everyone to switch all at once, and the benefits of primitives more aligned with the mental model of what we’re trying to do are undeniable.
This is delusional. Sorry, but you’re only shifting git with dynamite at this point.
No, git is not going away. It's not radically rejected. To the contrary, Jiujutsu builds upon git, and remains backwards-compatible, within reason.
It's like using Zig instead of C. You get a much better, handier tool, but you can interact with C very easily, transparently. You can mix and match.
Things like Monotone and Darcs were exquisite research projects, they tested many important ideas, but could not hope to become the standard. Jiujutsu does have this chance.
Problem with GitHub is that the VCS is in the name, so they would have to re-brand themselves (which might end up in losing loads of users) before they start supporting an alternative VCS.
I agree anyways, replacing Git is or would be a very difficult task in many cases.
That said, let us say I have a team of 3 people and we are starting a new project. We can definitely choose something other than Git, like Darcs (or later Pijul). If we use a project management software that only supports git, however, then that would be a very limiting factor. We probably would just continue using git, or use another project management software or I have no idea. I have used Git most of the time ever since I started using VCSs.
But that’s what’s so great about jj vs pijul: it supports git as a backend. So you still get to use GitHub and all the things that go along with git.
Git as a backend (with some amendments) is lovely and brilliant. Git as a front end is legendarily difficult to use.
Jujutsu has all the advantages with none of the downsides and—unlike the alternatives—adoption doesn’t need to happen all at once. Every single person who I’ve convinced to give it a meaningful shot has fully converted. That speaks volumes.
any advice on learning jujutsu? i keep bouncing off tutorials and blog posts about it. i’ve had a difficult time trying to map the github-centric branch-based workflow to jj. i’m sure part of the problem is “don’t try to use it like git”, but i haven’t gotten to the aha moment where it clicks.
You can 100% use it with that workflow, and there is no problem in doing that. You could use other workflows but those are things you can pick up as you gain more familiarity.
What I would focus on is what it enables you to do that’s hard in git: editing and revising commits that you’re iterating on, extracting out a large block of work into smaller commits, or splitting unrelated work out into a separate branch without needing to do a bunch of stashing, jumping around between branches, rebasing, etc.
Hell, even just being able to switch branches without having to do a wip commit or mess around with the stash is worth the price of admission to me. And having all of my work tracked during a long rewrite even if I don’t think to make checkpoint commits along the way.
But yeah, I’d 100% focus on what new superpowers you can add to your existing workflow before trying to actually change your workflow.
Just dive in and force yourself to use it. Keep the branch based workflow until you are more comfortable with the tool. Then try more exotic workflows.
jj git fetch to pull upstream main.
jj rebase -d main to rebase your branch on main
As you add commits to your branch jj bookmark move to update the branch then jj git push -b branchname to push it to remote
Also I highly recommend a couple neovim plugins: hunk.nvim for splitting commits and jjdiffconflicts.nvim for resolving conflicts.
I yearned for something like jj before I knew of magit. I was very used to the hg way of doing things and so git is a downgrade. But with magit I'm satisfied enough that I haven't felt a need to switch. Going back to typing commands in a terminal felt backwards. And magit makes a lot of things easy, like splitting commits (u on the hunk and then c e c -a c), moving commits from one branch to a new branch (A s), and moving commits from one branch to another (r s). What makes jj better than magit?
magit can only be as good as git.
jj’s first class conflicts and the way it handles rebase offers a UX that’s not possible with git.
Like with jj rebasing a stack of branches is just a single command. In git you would have to rebase the branch at the top and then hard reset each branch pointer one by one. jj’s rebase is just more powerful than git’s. Like it doesn’t just rebase a linear series of commits it rebases merge commits, other sibling branches, etc… it’s absolutely mind blowing.
https://ofcr.se/jujutsu-merge-workflow/
I really want to use something like Darcs or Pijul, but Pijul is not ready yet, AFAIK.
I'm a long time magit user and jj is basically just how I just git! At least close enough. I owe most of my git proficiency to magit. I understand how people are confused by just using the CLI. So I'm all for higher level tools like jj. Don't think I could give up the magit interface, though, unless there's something similar for jj?
How were you able to tell?
A terminal based CLI? As opposed to what?
I think they mean it is an interactive type terminal program (vs "one shot" as the git cli itself).
From the GIF in the repo I think it's somewhere between CLI and TUI -- it's interactive but does not try to draw windows/surfaces in the terminal. But the borderline is fuzzy, so yeah
The most popular CLI today is the browser's address / search / everything-else input control.
CLI as a paradigm is not necessarily related to emulating 1980s DEC hardware.
Naming suggestion; you’re too close to gcc for my brain to see the difference.
I agree!... Definitely confusing...
I'm kind of relieved to see that it calls out to the native git binary. There is a popular pure-Go git implementation that is in my experience very slow.
Pedantically, I think you probably would call this a REPL rather than a CLI
> Requirement: git command must be installed
holdup... is this just a wrapper around git?
> cmd := c.execCommand("git", "branch", "--format", "%(refname:short)")
oh my god. you have just wrapped standard git CLI. well, this is dissapointing.
Not sure what you expected? That's the case for all git clients (is there any using libgit?) and almost certainly the right thing to do
I'm aware of go-git [0] which
> aims to be fully compatible with git, all the porcelain operations are implemented to work exactly as git does
written in pure go, therefore with a go native api.
I've never tried to use it, but it does look quite impressive to me.
[0] https://github.com/go-git/go-git
it’s slow, not great. at a previous place we used go-git and wound up switching to just shelling out to git.
I've used it - it's lacking a ton of features. Another commenter in this thread said it's very slow compared to the git CLI, which is not surprising given that git is written in C.
I’ve used it for a production service. I thought it was surprisingly robust/featureful. There was one issue I ran into, but IIRC it was a limitation in the library’s filesystem abstraction, not a missing feature.
I would have used libgit2 myself in any languages. If bindings do not exist, I would have made the bindings first. There is no way I would have called out to an external program.
Someone mentioned https://github.com/go-git/go-git. I would have definitely used it unless there are better alternatives. If - as someone who claimed - it turns out it is slow, I would have created my own bindings to libgit2 still, most likely.
Binding to C in Go is a bad idea typically. There’s performance overhead, but more importantly your library (and everything downstream) also loses the ability to do nice things like fast compile times or easy cross compilation. You also likely introduce a runtime dependency on libc if not libgit2, so you have some DLL hell to deal with.
Is the performance overhead significant? Is it worse than calling out to an external program? Are there any benchmarks on this?
> Is the performance overhead significant?
How do you define significant? It is noticeable as compared to C. It is nothing compared to Python.
> Are there any benchmarks on this?
You will see an additional ~20ns per call (assuming the gc compiler; tinygo, for example, can call C functions as fast as C can). In other words, you're not ever going to notice unless you're making millions of calls in a hot loop. The bigger problem in a highly concurrent environment is that blocking C functions can start to mess with the scheduler if they are slow to return. You, again, would never notice in a program of this nature, though. The feature is there to be use. It being a "bad idea" is nonsense.
Some added pain in compilation is, fairly, a tradeoff to consider. But that's just because C compilers, for the most part, aren't very good. It is not like those problems go away if you use C instead.
Yeah, but for this project, why would you choose (as others stated they would or prefer) to call out to an external program instead of using https://github.com/libgit2/git2go (libgit2, FFI) for example? For what it is worth, there is also a pure Go implementation: https://github.com/go-git/go-git (pure Go).
Keep in mind the initial comment, which is "I would have used libgit2 myself in any languages.", and they claimed it is a bad idea due to performance, as opposed to calling out to an external program.
> and they claimed it is a bad idea due to performance
Which, as before, is nonsense.
Thank you, thought as much. I hope I will get a response from the person / people claiming this.
> I hope I will get a response from the person / people claiming this.
You want more nonsense...?
No, I want people to be informed well, and that requires me to hear their side so I can dispute them.
Many people has said they are thankful it calls out to "git" instead of using FFI, which I think is weird, but then there are others who go ahead and say that it is a worse thing to do, and I want people to know that no, it is not.
Jujutsu (jj) was using libgit, but they migrated away to wrapping the git cli several versions ago.
I’m not sure I see from your example why? You’d expect any git client to have branch.