Git is bad. Here's how I'd make it better
Here’s how I know it’s bad:
I’ve been coding for fifteen years, and I still need Google (or ChatGPT) to figure out which arcane Git incantation will undo a bad change. I bet you do the same. It’s so painful that I sometimes wonder if we’ll reach AGI before we see a simpler way to save code.
What is Git, fundamentally?
At its core, Git has two major parts:
1. On-disk data structures: Trees, blobs, and metadata sitting inside your .git folder.
2. A CLI with a confounding set of commands: A confusing interface for updating and transporting that on-disk data.
The data structures themselves? I don’t have much beef with them. Sure, they slow down at massive scale and don’t love giant binary files, but for most people, they’re good enough at storing code. The real problem is the CLI: a complicated web of dangerous, hard-to-remember commands. Every year, thousands of new developers struggle through bootcamps and college classes, nervously typing git push -f while praying they don’t vaporize 40 hours of work. At this point, learning Git has become a cultural hazing ritual. We shouldn’t be okay with that.
How would I fix Git?
I’d keep the underlying data structures but ban users from interacting with them directly through vanilla Git. Instead, I’d replace the sprawling set of Git commands with a simplified interface that’s easy to learn and hard to break. I’d throw away or hide 90% of concepts that only make sense in open-source development and optimize entirely for trunk-rebase-squash workflows.
Who is this for?
I’m aiming this at new grads, early-career Bootcamp engineers, and anyone who wants to focus on their code rather than wrestling with their version control system. If you’re a terminal wizard who loves wielding Git like a chainsaw, great—this isn’t for you. It’s for those who wish Git had never been invented and just want a simpler way to make changes and get them reviewed.
Inspiration: Jujitsu
Jujitsu (https://github.com/martinvonz/jj) is a Git-alternative that’s onto something. It wraps the .git folder in a parent directory, gently blocking raw Git commands from wreaking havoc. With one simple wrapper, they remove a massive footgun while preserving the underlying Git store. You can still “escape” if you need to, but by default you can’t accidentally blow up your repo with a stray command.
A Simplified Set of Commands
In a modern, closed-source development environment, you can throw out 90% of Git’s complexity. At the end of the day, what does a beginner really need?
• Clone the code
• Save my current diff (think: create a new change)
• Submit that diff for review
• Create a new diff based on trunk (or off an existing diff)
• Open (checkout) an existing diff to continue working
That’s basically it. The rest—merge commits, complicated branches, rebasing, staging areas, and intricate commit histories—just aren’t necessary for most everyday workflows. Big companies have already started to codify simpler practices:
• They use trunk-based workflows.
• They force squashing upon merge, so you only get one commit per branch.
• They ban merge commits.
• They require pull requests to merge into trunk.
These are real-world constraints that are becoming increasingly common. Extending these constraints locally would remove decision fatigue and complexity. You no longer have to choose between rebase or merge commits, or puzzle over whether your feature branch should have multiple commits. You’d have a simple, single-commit branch flow. Trunk stays clean, updated, and protected from accidental changes.
Let’s Call Them “Diffs”
“Changelists,” “Branches,” “Pull Requests”—these all carry historical baggage. In a simpler world, I’d call code changes “diffs.” A diff is literally just the difference between your code and the trunk. It’s short, easy to say, and aligns directly with the mental model of what you’re doing: making a small difference to the codebase.
A Peek at “Simple Git” Commands
Imagine a new CLI tool—call it sg (short for Simple Git). Here’s what that might look like:
# Clone the repository (under the hood, just a git clone)
sg clone https://github.com/myorg/myrepo
# Create a new diff off trunk
cd myrepo
sg diff create --name "add-user-auth"
# Open the diff (switch to it)
sg diff open add-user-auth
# Make changes locally, then save them
# Instead of 'git add' and 'git commit', we simplify it:
sg diff save "Implement initial auth logic"
# Submit diff for review (push a branch and open a PR)
sg diff submit
# This would automatically squash commits into one, push to a remote branch, and maybe open a PR.
This hypothetical CLI abstracts away Git’s complexity. Under the hood, it’s still using a single-commit branch, force-pushed (with lease) to the remote. But the user never sees that mess. They just see their diffs as safe, isolated units of work—like videogame save files that can’t easily break the world.
Undo Like an “Apple Time Machine”
Another improvement: a built-in time-travel undo. When I was first learning to code in high school, I’d store my repo in Dropbox. It was a terrible idea for performance, but it gave me a superpower: I could restore the project to a previous timestamp. Break everything at 8:00am? No problem—just roll back to 7:45am and pretend the disaster never happened.
Simple Git could integrate a similar concept. Maybe something like:
# View a timeline of recent states
sg timeline
# Restore the entire repo to a previous state
sg revert --to 2024-12-10T07:45
This would rely on snapshotting and deduping under the hood, making version control feel more like a time machine rather than a landmine.
For the Masochists: A Dangerous Escape Hatch
Some people just love the complexity. For them, I’d include a single “break glass in case of emergency” command:
sg dangerous git ...
This command would pass arguments directly to raw Git. You could do insane stuff here—create merge commits, rewrite histories—whatever. But at least you’d have to type “dangerous” to make it clear you’re stepping outside the safe zone. And if something goes horribly wrong, you’ve still got sg revert.
Is It Morally Wrong to Hide Git’s Complexity?
No. It’s morally wrong that new developers have to learn Git’s baroque interface in the first place. The original spirit of Git was about making it easy to collaborate on code. Over time, we’ve buried that under layers of complexity. Simplifying the interface and focusing on what modern workflows actually need would make coding more accessible. It would remove archaic barriers and help new developers get straight to what matters: building something cool.
If a new generation of devs grows up never having to memorize `git reset --hard HEAD~1`, is that really a bad thing? Or is it exactly what we need to make coding more humane and productive?
In the end, Simple Git would bring a world where version control is safe, intuitive, and understandable by default—a version control system that feels less like a hazing ritual and more like a helping hand.