Git needs a new interface
I’ve been a git advocate for a while, and I use git in two different projects. I think git is an impressive technical accomplishment, but I think its interface (”porcelain”) is not ready for prime-time. I really hope some UI-focused person will design a “v2″ for the git interface so that someday git can be the obvious choice for version control for any project.
Specific problems:
“checkout” is a destructive command
I seriously have no idea what Linus was thinking. It is insanity that:
$ git checkout foo.c
…will overwrite any local modifications you may have to foo.c without asking.
You can’t merge upstream changes into your local, uncommitted modifications
Suppose I cloned some repository and I started hacking it up. My changes are still hacky and not ready to be committed. Say a few days later I want to pull upstream changes, but without committing my hacky changes to my local repository:
$ git pull remote: Counting objects: 5, done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From /tmp/foo e726259..e20c51a master -> origin/master Updating e726259..e20c51a error: Entry 'foo.c' not uptodate. Cannot merge.
Git is refusing to perform a merge of my local modifications with the upstream changes. It wants me to commit my local changes first. This is annoying. Every version control system I have ever used supports this, except Git. Asking me to commit my hacky changes is unreasonable; they’re hacky and unfinished. They might not even compile!
Yes, I could do:
$ git stash $ git pull $ git stash apply
But why should I have to do this? CVS, SVN, and P4 don’t make me.
Git’s merge conflict resolution workflow is unintuitive
Continuing with the above example, now suppose I committed my local changes and then did a pull, but the changes were conflicting:
$ git pull Auto-merged foo.c CONFLICT (content): Merge conflict in foo.c Automatic merge failed; fix conflicts and then commit the result.
Ok, git is somewhat helpful here, I’ll fix the conflicts in foo.c and commit the result:
$ vim foo.c $ git commit foo.c: needs merge foo.c: unmerged (f388ef85dd65c39e4c76f5e597d3b67f7d1a0726) foo.c: unmerged (6f4bf54585ae256236c0d6cfa9f114affb94313f) foo.c: unmerged (06c974ebbfc04394f4fad8a6dcb31e64866fa1bf) error: Error building trees
Ok, maybe it’s obvious to experienced git users what my error is here, but git’s error message here is worse than unhelpful — it’s downright confusing. I think I’ve resolved the conflict, but all git can think to do is tell me is that “foo.c needs merge” and spit some SHA1’s at me. It gives me absolutely no help about what I need to do to fix the problem.
Suppose that I want to resolve the merge by using either my version or their version verbatim (”accept mine”/”accept theirs”):
$ git checkout foo.c
error: path 'foo.c' is unmergedAgain, unhelpful (and in this case, what I’m trying to say actually makes sense, git just won’t let me do it).
Interface for working with the index almost universally confusing
I understand the difference between the working directory, the index, and the committed tree pretty well. But I cannot for the life of me remember the difference between:
$ git reset --soft $ git reset --hard $ git reset --mixed
I can barely keep them straight while I’m reading the manpage. “Soft” resets HEAD but not the working directory or index. “Mixed” resets HEAD and the index, but not the working directory. “Hard” reset HEAD, the index, and the working directory.
In conclusion, this isn’t meant to be an exhaustive list of problems with git’s interface, it’s more meant to be a microcosm. Git’s interface is not intuitive or easy to learn, and its error messages are not helpful. Which is too bad, because as I said I think Git is solid technology. I just hope someone writes a better porcelain for it. I’m not talking about evolutionary changes, I think the suite of top-level commands (checkout, branch, merge, pull, reset, commit, etc) needs to be redesigned from scratch.
Recent Comments