Git is a beautiful work of engineering. It's blazingly fast even on massive repositories, and it efficiently manages vast numbers of branches.
These qualities have made git the dominant source control system, even though it's hard for humans to use.
So what's wrong with git?
Git commands are too many, too low-level and hard to understand.
The git program is a collection of 157 commands:
The sheer number of commands is a problem. Even though it's pretty easy to master the most common 10 commands for day-to-day coding, you often run into commands you've never seen before. So git makes you feel like you're always a beginner!
Also, git commands are low-level operations, so they don't map exactly to things you want to do.
You need multiple commands to execute common actions (like "put my code on GitHub" and "make my coworker's code available in my editor").
Finally, some of the commands do quite different things depending on
their parameters (e.g.,
git reset and
git checkout), making them
hard to understand.
Git has been trying to create less confusing commands (like splitting
git checkout into
git switch and
git restore), but this
creates even more commands to learn!
Git tracks 4 versions of files, instead of just "my" version and "the team's" version.
When I'm working on a file, I mostly think about "my" version (what I'm working on in my editor) and "the team's" version (what the file looks like on GitHub).
Unfortunately, git has two more versions that I need to keep in mind: the one in the "index" (or "staging area") and the one in the HEAD commit in my local repository.
Because of the low-level commands and the 4 different versions, there's no single git command that tells git to just take a file I saved in my editor and update GitHub. Instead, I have to do the following:
# disk -> index/staging area
git add README.md
# staging area -> local branch
# local branch -> remote repository (e.g., GitHub)
git push origin branch
(The first two commands can be reduced to one with
git commit -a,
but beware: that will only add changed files and skip any new files you
created while coding.)
Clearly, the 4-version internal git model complicates most common tasks.
Git doesn't let us safely experiment
Most of us learn new tools by experimenting with them, but git is not set up for experimentation. It lacks "undo", "--dryrun", and safeguards against you deleting your own code.
- Undo would allow you to try some commands and backtrack if they don't lead to the right result.
- A dry run parameter would show you a summary of what a command does without making actual changes. If git had that, you could confidently explore commands and preview the effects before applying them.
- Finally, a safeguard against deleting code could prompt you with an
extra warning before executing commands like
git reset –hardor
git push –force origin1. If all commands that might cause you to permanently lose your data had a safeguard, you could experiment more.
Because these three features are missing, you can't casually experiment with git commands unless you want to risk losing code you spent hours working on.
In summary, git forces you to convert commands that make sense to you into commands that make sense to git, and it punishes you for any mistake you make.
The way forward: new tools will improve the git user experience.
Despite the user experience issues, git will probably not be replaced by a new source control system. Instead, new tools on top of git can make it easier to use by converting commands that make sense to humans into commands that make sense to git. They will offer us fewer, more meaningful commands, automatically manage the 4-version model of git and make experimentation easy and safe.
Several tools are already out there:
- Gitless 2
- Sapling: just opensourced yesterday by Meta
- HighFlux: our product, currently in beta
Mathijs is one of the co-founders of HighFlux.io
HighFlux is a CLI and GUI that incorporates these ideas and is currently in beta.