Git sucks

The Git version control system has been causing us misery for 15+ years. Since its inception, a thousand people have tried to make new clients for Git to improve usability.

But practically everyone has focused on providing a pretty facade to do more or less the same operations as Git on the command-line — as if Git’s command-line interface were already the pinnacle of usability.

No one bothers to consider: what are the workflows that people actually want to do? What are the features that would make those workflows easier? So instead we get clients which think that git rebase -i as the best possible way to reword a commit message, or edit an old commit, or split a commit, or even worth exposing in the UI.

Rubric

I thought about some of the workflows I carry out frequently, and examined several Git clients (some of which are GUIs and some of which are TUIs) to see how well they supported these workflows.

Many of my readers won’t care for these workflows, but it’s not just about the workflows themselves; it’s about the resolve to improve workflows by not using the faulty set of primitives offered by Git. I do not care to argue about which workflows are best or should be supported.

Workflows:

  • reword: It should be possible to update the commit message of a commit which isn’t currently checked out.
    • Rewording a commit is guaranteed to not cause a merge conflict, so requiring that the commit be checked out is unnecessary.
    • It should also be possible to reword a commit which is the ancestor of multiple branches without abandoning some of those branches, but let’s not get our hopes up…
  • sync: It should be possible to sync all of my branches (or some subset) via merge or rebase, in a single operation.
    • I do this all the time! Practically the first thing every morning when coming into work.
  • split: There should be a specific command to split a commit into two or more commits, including commits which aren’t currently checked out.
    • Splitting a commit is guaranteed to not cause a merge conflict, so requiring that the commit be checked out is unnecessary.
    • Not accepting git rebase -i solutions, as it’s very confusing to examine the state of the repository during a rebase.
  • preview: Before carrying out a merge or rebase, it should be possible to preview the result, including any conflicts that would arise.
    • That way, I don’t have to start the merge/rebase operation in order to see if it will succeed or whether it will be hard to resolve conflicts.
    • Merge conflicts are perhaps the worst part about using Git, so it should be much easier to work with them (and avoid dealing with them!).
    • The only people who seem to want this feature are people who come from other version control systems.
  • undo: I should be able to undo arbitrary operations, ideally including tracked but uncommitted changes.
    • This is not the same as reverting a commit. Reverting a commit creates an altogether new commit with the inverse changes, whereas undoing an operation should restore the repository to the state it was in before the operation was carried out, so there would be no original commit to revert.
  • large-load: The UI should load large repositories quickly.
    • The UI shouldn’t hang at any point, and should show useful information as soon as it’s loaded. You shouldn’t have to wait for the entire repository to load before you can examine commits or branches.
    • The program is allowed to be slow on the first invocation to build any necessary caches, but must be responsive on subsequent invocations.
  • large-ops: The UI should be responsive when carrying out various operations, such as examining commits and branches, or merging or rebasing.

Extra points:

  • I will award honorary negative points for any client which dares to treat git rebase -i as if it were a fundamental primitive.
  • I will award honorary bonus points for any client which seems to respect the empirical usability research for Git (or other VCSes). Examples:

Since I didn’t actually note down any of this, these criteria are just so that any vendors of these clients can know whether I am impressed or disappointed by them.

Clients

I picked some clients arbitrarily from this list of clients. I am surely wrong about some of these points (or they’ve changed since I last looked), so leave a comment.

  • Update 2022-01-09: Added IntelliJ.
  • Update 2022-01-10: Added Tower.
  • Update 2023-05-28: Upgraded Magit’s reword rating.

I included my own project git-branchless, so it doesn’t really count as an example of innovation in the industry. I’m including it to demonstrate that many of these workflows are very much possible.

reword ❌ 1 ⚠️ 2 ⚠️ 2 ⚠️ 2 ⚠️ 2
sync
split ❌ 1
preview ⚠️ 3 ⚠️ 3 ⚠️ 3 ✅ 4 ⚠️ 5 ✅ 6
undo ⚠️ 7
large-load ✅ 8 ✅ 9
large-ops ✅ 8 ✅ 9

Notes:

  • 1 It can be done via git rebase -i or equivalent, but it’s not ergonomic, and it only works for commits reachable from HEAD instead of from other branches.
  • 2 Rewording can be done without checking out the commit, but only for commits reachable from HEAD. There may be additional limitations.
  • 3 Partial support; it can show whether the merge is fast-forward or not, but no additional details.
  • 4 Can be done via magit-merge-preview.
  • 5 Partial support; if an operation would cause a merge conflict and --merge wasn’t passed, then instead aborts and shows the number of files that would conflict.
  • 6 Jujutsu doesn’t let you preview merge conflicts per se, but merges and rebases always succeed and the conflicts are stored in the commit, and then you can undo the operation if you don’t want to deal with the merge conflicts. You can even restore the old version of the commit well after you carried out the merge/rebase, if desired. This avoids interrupting your workflow, which is the ultimate goal of this feature, so I’m scoring it as a pass for this category.
  • 7 Undo support is experimental and based on the reflog, which can’t undo all types of operations.
  • 8 Git struggles with some operations on large repositories and can be improved upon, but we’ll consider this to be the baseline performance for large repositories.
  • 9 Presumably Magit has the same performance as Git, but I didn’t check because I don’t use Emacs.

Awards

Commendations:

  • GitUp: the most innovative Git GUI of the above.
  • GitKraken: innovating in some spaces, such as improved support for centralized workflows by warning about concurrently-edited files. These areas aren’t reflected above; I just noticed them on other occasions.
  • Sublime Merge: incredibly responsive, as to be expected from the folks responsible for Sublime Text.
  • Tower: for having a pleasing undo implementation.

Demerits:

  • Fork: for making it really hard to search for documentation (“git fork undo” mostly produces results for undoing forking in general, not for the Fork client).
  • SmartGit: for being deficient in every category tested.

The following are hand-curated posts which you might find interesting.

Want to see more of my posts? Follow me on Twitter or subscribe via RSS.

Comments