What’s wrong with Git? A conceptual design analysis
blog.acolyer.org
blog.acolyer.org
1) A tool for managing collaborative work through a beautiful distributed graph theory tree model[1]...
2) ...with a very, very difficult to use UI. Unfortunately:
3) A good, intuitive UI for manipulating the underlying model without ignoring edge cases or removing functionality is extremely difficult, and indeed, nobody has done it yet.
So you periodically see these articles pop up decrying the UI, but nobody ever makes a great UI that wraps the underlying tools. This article talks positively about gitless, and it's a great tool, but it gets a good UX only be hiding/disabling large chunks of functionality. And like most tools...
4) Git suffers heavily from the 80/20 rule[2].
I'd say 95% of the time, I'm using maybe 5% of git's features. But the other 5% of the time, I'm using another 1% of git's features but it's always a different 1%. I might go weeks without needing to cherry pick a commit, but when I need to, I really need to...and gitless doesn't support it (or most other "complicated" features). But the reason git beat out the competition isn't git's excellent UI or large marketing budget, it's that those features actually provide significant value.
And so we get a slow drip of articles like this. "Man, it would be nice if there was a better git UI that had all its features!" It would indeed.
It appears as if the complexity of git has created a sort of Stockholm-Syndrome, where people mistake the flaws of the system for symptoms of its magnificent power, and dismissing all criticism with an attitude of "let the hobbyists have something with a shiny GUI, this a tool for professionals".
But what people are asking for is /not/ a shiny veneer hiding the complexity, but a rethinking of the concepts that git uses. "Concept" here means mostly the mental model people form of how git operates, but that is often linked to the terms used and the internal structure.
As an easy-to-grasp example, filesystems generally operate with the "tree" concept. Note that there's nothing mandating such a structure – you could create a fs that's based on tags instead. Or weaken the tree metaphor by allowing cross-connections (i.e. linking). But given the choice of one concept, it creates certain assumptions about how to operate the system. And when those break down, people rm -rf and start over. Way to often.
That makes me a bit sceptical about whether the authors really thought through all the various use cases of git, i.e. those 5% that the GP comment talks about, and about their conclusions.
> “the elimination of the staging area was enthusiastically received as a major reduction in complexity.”
But I'm using it regularly. This is the feature that makes git stand out, even for casual users who typically edit things then commit (and have to sort things out to make sensible, semantic commits instead of "whatevs"). Every single tutorial glosses over it, but it's the single most important feature that hinges on what git is and how it operates at its core.
Every time I teach git, I take great care explaining why and how the staging area (the index and git objects, really) works. Every single time I explain that you're preparing a transaction that you end up committing (with all relevant — but obviously wrong — database or journalling filesystem analogies). And every single time, it just clicks.
To design a great interface, first you have to come up with a good metaphor and a great name. That's the first obvious fail, because the staging area has at least three different names in common use. As you said yourself, once you use a metaphor to explain the staging area, it just clicks. With a good name, the metaphor should be obvious.
And then you have to supply a consistent, non-surprising interface. What's the staging area? It's essentially a commit-in-progress. So why does it have a different interface than git commit --amend?
Grumpy me is really disappointed that git itself subsumed the porcelain. There were some really good ideas floating out there that fell by the wayside as git became usable by itself.
Stacked Git, for instance: http://www.procode.org/stgit/
We should have had a bunch of porcelains that evolved to a nice shine. You should have been able to switch back and forth between porcelains.
Aha, that's where the typical view of VCSes shows through the cracks of our old habits: here commit is not an object, it's an action. So there's no "commit-in-progress" because either you commit or you don't, and the operation is virtually atomic. The fact that object with badcafe sha1 records the history of that action and is called "commit badcafe" in the log is incidental, and we're being abusive when we're literally saying the commit is the object.
So when you say git commit --amend, it's really no different than git commit, because you're just telling it to do the very same thing, only with a git reset HEAD^ before that.
That said, I'll readily admit the UI is poor, mostly because it's grown, not designed.
I don't think either of us is wrong, we just use different names, making communication very difficult. Which just underscores my original point. Names matter.
That's basically what Magit is, a porcelain for git. It actually adds operations beyond what git's own porcelain allows, and makes easier the ones it does allow. Using Magit is like being a git ninja compared to using the CLI.
I tend to think that the reason git beat out the competition is github. It was the first VCS hosting service that actually provided a sane UI that enabled non-vcs-experts to at least observe what's happening. github doesn't provide an interface to a lot of gits features and so do the github-provided native clients, but they are sufficient for at least 50% of the population that I know. Many people don't know and/or don't care about all the other power_features that git provides.
I don't know if it's true for everyone, but this is at least true for me. The reason I started to work on a git remote helper to talk to mercurial servers is that I grew frustrated that mercurial didn't have some of those features (and that the existing git remote helpers were not working well at the scale of mozilla-central, or required a local mercurial clone under the hood)
What features were you missing, by the way? Mercurial has had rebase, squash and light branches (bookmarks) for many years now. I personally don't miss staging if I use it.
> Not sure if those were committed back.
Some were for sure: [1]
I'm most inclined to believe that it certainly was git's large marketing budget that got it to where it is today. Not a monetary budget, but its reputational budget: "Written by Linus" so it must be good.
So you can't selectively stage hunks and discard others? Or stash them after making a commit of the ones you staged?
> the elimination of the concept of Stash, and stashed versions;
This eliminates the possibility of quickly putting away work in progress to do an impromptu demo at your desk, or answer a co-worker's question about the current master, or (for git newbies) working effectively with git-svn (in companies where SVN is used) without needing to learn about local branching or rebasing.
> Thus, it is as if there are multiple working directories (one for each branch),
So...like Subversion? Ew.
Does git have sharp edges? Absolutely. It's a tool meant to be used by professionals (or skilled hobbyists) to do work and build things.
I'm all for making things simpler to use, but putting training wheels (or guardrails) on a product meant for an expert user seems...counter-productive to me. To me it's like saying "Gee that cockpit has an awful lot of dials and instruments and things, we could probably take out a lot of the complexity if we assume that pilots will never have to deal with a stall" (I know nothing about planes)
I am also willing to admit that perhaps I'm too wedded to the time investment I've put into learning git and therefore assume that anything that attempts to make git simpler is flawed in some way. Maybe gitless really is the future of git.
As other people have pointed out, most new version control tools can do this without a staging area.
This eliminates the possibility of quickly putting away work in progress to do an impromptu demo at your desk,
No it doesn't, and they explain how. With combined branches + stashes, you'd do a checkout of a new branch from the commit before your stashed changes.
So...like Subversion? ... putting training wheels (or guardrails) on a product meant for an expert user seems...counter-productive to me.
Did you even read the article or the original paper?
This sole function built in is a game-changer in mercurial for me.
That said: Partially commiting files is indeed very handy and it would be great if it was available to more people.
Fair enough.
> No it doesn't, and they explain how. With combined branches + stashes, you'd do a checkout of a new branch from the commit before your stashed changes.
Ah, OK. However, I still maintain that I have other uses for stash that don't easily conform to git stash --all; git co new-branch.
I read the article (though it appears not closely enough). I will admit to not reading the original paper (until now), but I did skim gitless's documentation a few weeks back when it appeared on HN. Even then I was struck with a touch of "What is all this new s&%# I like how my git is right now stop messing with it"
Like I said, I'm willing to admit that because I already know all of git's sharp edges, gitless may simply not appeal to me. However, it's totally possible that gitless really does make git simpler for new users and it's the future of git.
scm stash <filename> # Stash a whole file
scm stash -p <filename> # Stash a part of a file
scm stash -p # Stash parts of the whole project
Works as well as a staging area (because it's just the complementary operation) without needing a staging area, and without all the cognitive burden. Saying "you can put changes aside for later" is much easier than explaining the different states of a file in the staging area.
Most of the time, criticism of git can be summarized as "Bad user experience", which is often blamed on git exposing its implementation details. I.e. most git criticism proposes that the backend of the VCS should be "private" and the user should see a carefully designed UI, that is optimized for workflows.
I think we don't need to redesign git in such a way, for the mere fact, that we already have a mature, distributed version control system that has a carefully designed UI and has a core that is opaque to the user: mercurial
In fact, given mercurial's age, the availability of github-like hosting services (bitbucket offered mercurial hosting for years) raise a very important question, that I would like "git-reformists" to answer as part of their critique: Why has git won more market share than mercurial?
My feeling is, that part of what makes git hard to new users is a "killer feature" for intermediate and advanced users. I.e. having a basic understanding of how git manages its data makes hardly leaves me with situations and repository states that I cannot resolve. Whereas in mercurial, I feel pretty much lost when I want to do something that has not been an implemented workflow.
Maybe, now that we know a lot more about DVCS workflows than we did at the time when mercurial and git were young, a new workflow-oriented VCS might make better workflow choices. Until then, I happily stay with git.
Because Git is used by Linux and was designed by Linus.
Those facts alone are good enough for most people to choose git over something else, not the technical ones.
Just like UNIX and JavaScript, technically better is not always what wins.
Honestly it's a good story about the power of marketing and I feel a bit sorry for the monotone developers because they did it first and well, but get almost no recognition.
Fast?
I played with OpenEmbedded (for OpenMoko) a while ago, which used monotone. From what I recall, it was slow. IIRC, slow enough that they had to use the trick of downloading a "pre-cloned" snapshot and updating it, instead of cloning from scratch.
I did find some benchmarks from 2009 and by then monotone shows consistent by often 5x slower performance than git:
https://web.archive.org/web/20090131095353/http://ldn.linuxf...
"Worse is better" etc.
(Completely unrelated, I just discovered that the Plan 9 logo bears a striking resemblance to the Go logo [see the Wikipedia link]. Given Rob Pike's influence, I'm sure that is not a coincidence.)
Git is great, compared to most of the alternatives. But is it perfect? Of course not. Is it hugely flawed in parts? Of course it is. It has a UX designed by freaking engineers FFS, it's surprising it's as usable as it is.
The observation that git forces you to learn how its guts work so that when you inevitably end up in some scary situation with the potential of losing or screwing up revision history you know enough to work your way out of it is not a strong argument. It's similar to the lament about how older cars were so much easier to work on and that made them better. Better if you want to work on cars, perhaps, but a vehicle that requires constant maintenance is not superior to today's cars that can be run for 100k miles with minimal engine work and a single set of spark plugs, and are also safer, more efficient, and cleaner to boot. The same thing goes for VCSes, if you're regularly, or ever, getting into hairy revision history problems that's a sign of a weakness in your VCS and/or workflow.
If your dvcs allows you to get to that odd situation then it's already bad. Think about it as a tool for masses, maybe someone really familiar with GIT internals can resolve all odd situations, but imagine introducing GIT into an Organization with 1000 SVN users. The costs of all the guys learning in depth git is just too big.
GitHub _is_ a huge success, and git is merely comes along in a bandwagon (English isn't my native, hope I've made this clear)
> Whereas in mercurial, I feel pretty much lost when I want to do something that has not been an implemented workflow.
Interesting, could you give an example?
It's the other way around. Git was such a huge success, so therefore someone decided to create a nice web-frontend and SASS for it. That SASS was Github.
I think it's only difficult to use if the company/people using Git don't have good Git policy.
As far as I can tell, gitless still embraces git's distributed and incremental core. It just packages it in a way that's easier to digest. If you're a veteran and know your way around native git flawlessly, gitless probably presents little value. But if you're a notice just learning the tool, gitless can probably accelerate your learning curve without sacrificing functionality—you can still bypass gitless's abstraction layer when you need it.
"These weaknesses have spurred the development of com- mand line wrappers and GUIs whose primary goal is to re- move some of Git’s complexity (most notably, EasyGit [1] and GitHub’s desktop client). These make largely cosmetic changes, through more attractive user interfaces, more con- sistent terminology in commands and documentation, and a focus on more commonly used commands. But their suc- cess seems to have been fairly limited, and most people still use the command line interface distributed with Git as their primary frontend, or fall back to it for accomplishing more complex tasks.
We believe that the usability problems of Git run deeper, and can only be addressed by a more fundamental reworking that reconsiders the underlying concepts. This is not to say that such a reworking cannot be achieved in a lightweight fashion. Indeed, our own reworking hides Git behind a ve- neer just as these other tools do. The difference however, is that we are willing to completely reconsider the core con- cepts that are presented to the user."
Do the same with stash commits. Store them as regular commits flagged as broken and hide them when viewing history.
Hell, do the same for most history-modifying operations. The ability to flag intermediate commits as "unimportant" would let you be able to keep a clean history without rewriting it.
Maybe you want to share your work with others even though it's still in a rough state.
Maybe you have automated tests in your CI process and you want to try those tests on your side-branch.
The point is you might want to wrap workflow around your stuff, even if it's experimental and broken.
Git doesn't make these choices for you. You get to make them.
I find that making a work-in-progress commit, and then resetting later ends up saving a lot of hassle overall. Having support for this beyond aliases (including putting that commit in a new branch) would be nice.
Or debugging code. You're right, git add -p is a lifesaver.
The idea to remove the concept of the staging area to simplify git is worthwhile. I heavily use `add -p` myself, but newbies certainly struggle with it and teaching `commit -a` is not the solution.
No, because I don't run `git add -p` before committing (I would run `git commit --patch` for that). I run `git add -p` during the development cycle. To emulate this with `git stash` would require a very annoying dance with stash and rebase.
> newbies certainly struggle with it
Newbies don't even know about `git add -p`. Newbies struggle with git because commands are not orthogonal (as the article mentions), and because documentation sucks. There is nothing inherently difficult about the staging area, it's just that it's not very visible what object a command would use or affect (index/tree/working directory) and it's hard to learn this.
The problem is with the implementation, not with the model.
Another problem is that in most cases people don't really want git, they want svn with local commits and better merging capabilities. Git is very popular, for some reason people use it even if it's clearly not what they want or need. To these people I suggest they should use the DVCS features of Perforce.
Not having a staging area (or using git add . && git commit -a to bypass it) has it's drawbacks too; I think most of the "garbage" files like "main.o" and ".test.py.swp", and secret API keys in public repos, can be explained that way.
To me, the answer is not abandoning the staging area, but improving the UI for handling it and/or directing users that don't want to deal with the git UI to things like GitUp. The git UI is horrible in a lot of places, admittedly. Even now, considering myself an advanced user, my workflow still is "git branch ... uhmmm... ^H^H... git checkout -b topic".
Fixing the (most annoying issues of the) UI might require some breaking changes sometimes, but so be it.
git stash -k
Which will create the stash with your changes (both staged and unstaged), but keep the staged ones in the staging area and in the working tree.https://github.com/git/git/blob/659889482ac63411daea38b2c3d1...
Anyone that wants to use TYOOL 2016 age DVCS features should also switch. Like changing history yet still keeping a record of the original one (hg evolve).
Git completely owned all other DVCS with good branching. 10 years ago. But now it's time to move on to better tools.
Some companies even have Git, Mercurial, and SVN, working all together under centralized repository management.
Both git and mercurial can talk to "non-native" remote servers.
IIRC mercurial can talk to subversion and git (with hg-git).
Git can talk to subversion, cvs, perforce, mercurial (there are multiple tools for the latter, and I'm the author of one of them), bzr, and maybe others.
If things don't work smoothly in any of those cross-VCS configurations, my belief is that issues should be filed and fixed.
Working in a big firm adds overhead, yet has certain benefits (resources, etc.). That's a whole different topic though.
git add foo.rb
// continue working in foo.rb
git commit foo.rb
will commit the latest version of foo.rb.That's because git commit handles its arguments by add-ing them to the index (staging area) before doing the actual committing.
I'm not so sure about the conceptual graph from the paper, either. The stash is a commit, it doesn't have anything to do with file states.
3. by listing files as arguments to the commit command, in which case the commit will ignore changes staged in the index, and instead record the current content of the listed files (which must already be known to Git);
And I don't know if I'd call this error evidence of the author not understanding git, as much as I'd call it further evidence of the inconsistency they're highlighting.
That's not what it actually does. It commits all the changes from the file (staged or otherwise), and nothing else. It leaves the index/staging area in the same state, except for the committed file.
That is:
git add foo bar baz
git commit foo
will commit any change to foo, and leave bar and baz alone (staged and non staged parts).One of my problem for which I didn't find a satisfying solution yet is to efficiently see the changes in commits and reshuffle and merge them.
Actually, when I do a change, I offten see and fix typos and other bugs or refactor code in the same step. So my commits tend to be a compilation of unrelated changes instead of clean atomic commits. It is a boring work to split these commits into nice and clean commits.
I know I should commit frequently (small changes), and then afterward merge related commits. But that is not easy with git and I suppose gitless too. So I tend to do big commits which is bad. Any suggestion how I could improve my commits ?
It opens a text file listing your commits prefixed with a command, which you can reorder and edit to change the history in one go. It's not completely painless, and I still prefer to do operations one at a time with it in case there are any conflicts, but it's still better than the alternative. (I'm not even sure what I do instead...)
Just found a limitation in gitless. I can't publish tags.
In the time it takes to master git/emacs, one could have accomplished something seriously impressive.
Of course, this analogy doesn't completely hold because the basic functionality of git is pretty easy to use (especially with gui tools).
It's mostly a problem for them though, because it makes them an easy mark. You can get them to spend a significant chunk of their time on earth patching kernels to get their ethernet cards working, and they'll gladly do it and feel really quite manly and professional and not lonely at all, no.
As it turns out I do think both the porcelain and plumbing commands both suck, but I rather read a takedown by somebody who's learned all the layers.
I'm wondering how nice architecture under the hood can be an excuse to have an Boeing-747-cockpit-style UI?
Maybe Perforce or something, but recommending VSS in 2016? Hope it works out for you!