7 ms·
Linus built an incredibly elegant and simple underlying model for git. For what it successfully does - distributed version control - it is remarkably simple and
by bad_username 4y ago
Linus built an incredibly elegant and simple underlying model for git. For what it successfully does - distributed version control - it is remarkably simple and easy to grasp if you want to.
However, this model was not mapped well to the high level concepts that the typical user of a VCS operates in. This is the biggest issue of git: it's hard to make sense of it by its UI if you do not understand how it works under the hood. I struggled until I read the pro git book.
I wouldn't go as far as to compare this to knowing about filesystem data structures for saving a jpeg file. It's more like using an old school file dialog where you just see the bare file system and you need to know your way around your drive.
- josephg 4y agoGit's other (compounding) problem is how the CLI is an inconsistent mess. Why do you create a branch via the "git checkout" command? Why do you delete tags using "git tag -d" but delete stashes using "git stash drop"? If you want to blow away local uncommitted changes, you can use "git reset", "git reset --hard" or "git checkout (file)" - which (I think) all do totally different things. Git's data model may be elegant, but its hard to appreciate it through the tangled mess of git command line options.
- Nadya 4y agoI use Git daily and literally couldn't tell you how to use it because I've aliased every single command it has. I basically have a wrapper over it and to teach anyone how to use Git I have to peel my layer away and check what I have things aliased to. It feels like terrible ad hoc user design built over an otherwise extremely elegant and clean data model.
- freetonik 4y agoWould you mind sharing your aliases? Curious to see a different mental model.
- amadvance 4y agoThey tried to fix that mess, like with the recent git switch/restore. But it looks like it was too late.
- sampo 4y ago> Why do you create a branch via the "git checkout" command? Now there is also `git switch --create` / `git switch -c` for this. Perhaps in time, there will appear different front end dialects for git. Like the statistics programming language R has the base R language, data.table dialect, and the tidyverse dialect.
- anthomtb 4y agoThere is also `git restore` for reverting local or staged changes, the other common use of `git checkout`. I am slowly remapping my keystroke muscle memory away from the footgun that is `git checkout` and using restore/switch. But boy is it hard to undo a decade of practice.
- jolmg 4y ago> Why do you create a branch via the "git checkout" command? git checkout -b foo is just a shortcut for git branch foo git checkout foo > Why do you delete tags using "git tag -d" but delete stashes using "git stash drop"? That is inconsistent. One has an interface of `git <thing> <options-to-manage-thing>` and the other `git <thing> <subcommand-actions-for-thing>`. I imagine what happened is the former was the original and was probably thought to be sufficient, but then it wasn't for `stash` and the latter was introduced for more flexibility. The inconsistency is probably from backwards compatibility. It might be worth noting that, at least as far as I know, git was like the first to use or at least popularize subcommands. It'd be understandable if they didn't include support for sub-sub-commands from the get-go. > If you want to blow away local uncommitted changes, you can use "git reset", "git reset --hard" or "git checkout (file)" - which (I think) all do totally different things. git-reset is mainly about resetting the branch, index, and/or working tree to a given ref. git-checkout is mainly about checking out a ref, setting HEAD and syncing the working tree to it. They're different things with an overlap. I would say that's not really inconsistent. It would only appear so when one only learns specific patterns of commands for subsets of their function, like "blow away local uncommitted changes", which in this case fits in their overlap.
- josephg 4y agoThat can all be true, but it doesn't make git any less of a nightmare to learn. Even very experienced git users make mistakes and need to google things all the time. Its become almost a trope at multiple places I've worked that even once in awhile someone makes a mess of their git repository, and needs to call for help from one of the 2 people in the entire office who understand git enough to unbreak it. Another annoying inconsistency: git tag prints a list of tags. Git branch prints a list of branches. Git commit prints ... modified files? And git stash modifies the stash. You need git stash list to see the stash. What!? I get it; its a complex tool. Its managing 4 different storage areas for your code (the repository, the staging area, the index and the stash). It also manages tags, branches, remotes and configuration. And it has multiple networking interfaces. But I can't escape the conclusion that its just not a very good user interface. A good interface wouldn't be so hard to use. Redis is more complex, but I don't make so many mistakes using the redis cli. Awk is more powerful - but its much more intuitive. And cargo probably has more subcommands than git does, but I don't get lost in them. Git? Git is a mess.
- Oxidation 4y agoI know what you mean (deleting a branch in a remote is a very unintuitive syntax to me at first glance, especially), but these are perhaps not the best examples: > Why do you create a branch via the "git checkout" command? That's a shortcut for "git branch (name)", then "git checkout (name)". Or the newer "switch" which is more obvious. > Why do you delete tags using "git tag -d" but delete stashes using "git stash drop"? Because the stash is more like a stack, and tags are not, so "drop" without a parameter is a valid and very usual command. Yes, it feels inconsistent, but allowing "git stash -d" without a parameter would probably not be better. > If you want to blow away local uncommitted changes, you can use "git reset", "git reset --hard" or "git checkout (file)" - which (I think) all do totally different things. These do all do different things, so that's why they all exist. "git restore (file)" was introduced a few years ago (with "switch", mentioned earlier) to make the last one more obvious, since that's indeed always been an uncomfortable syntax for a core operation. Git's a very powerful tool, originally aimed at a very complex code base run by experts, and was written very quickly as an emergency replacement for BitWarden. This rushed development and target audience does show through even today, but it's being annealed over time. Nevertheless, it's so good at what it does that it's taken out nearly every other VCS by just existing (ok, and the network effects of GitHub, but they choose it for a reason too).
- martijnvds 4y agoBitKeeper was the version control system. Bitwarden is the password manager.
- foresto 4y agoOne of my favorite examples of this is the cache. I mean index. I mean staging area. Sigh.
- OkayPhysicist 4y agoHow else would you support breaking up a change into multiple commits?
- anthomtb 4y ago`git stash -p`
- erik_seaberg 4y agoThis. I stash what I don’t want to test and commit, because I can’t build or test the staging area.
- wolfgang42 4y agoI’ve been toying with various ways to do this. Some alternatives I’ve thought of: - a “draft commit”, where you can amend a bunch of changes into a commit before finalizing it. - default to “git commit --all”, and allow the user to “git commit --patch” where needed - as 'anthomtb says, `git stash push --patch` (I also find myself wishing for `git stash pop --patch` so you can shove bits in and out of a stash as needed.)
- OkayPhysicist 4y agoIsn't a "draft commit" the same thing as the staging area?
- wolfgang42 4y agoThe main differences I’m imagining are: a) terminology: it’s one less concept to have to wrap your head around; and b) a draft commit would also have a draft commit message, and (though I’m admittedly not sure about how well this part would work), draft parents (probably supporting refs rather than just commits as parents) so you can have multiple of them and shuffle them around conveniently. (This also sort of subsumes the stash as well.) I made a preliminary stab at this a while back, though it has some awkwardness and I haven’t had a chance to revisit it recently: https://github.com/wolfgang42/git-draft/ https://github.com/wolfgang42/git-draft/
- lmm 4y agoSo what's the underlying model that makes the staging area make sense? Why does stash followed by unstash leave my checkout in a different state from what it was before?
- JonathonW 4y agoThe staging area is where you construct your next commit— giving you a middle ground between your changes in your local working copy and the last actual commit so that, if you don’t want to commit everything that you’ve changed in a single commit, you can do that. (If you always want to commit everything you’ve changed, you can do that too— always commit with ‘git commit -a’ and only use ‘git add’ when dealing with new files that you want to add to version control.)
- iggldiggl 4y agoHmm. With Mercurial I just use "commit --interactive" if I only want to commit part of my changes, and I always found that more intuitive and less confusing than having to mentally keep track of Git's staging area as well.
- OrderlyTiamat 4y agoThe git analogue to that would be `git commit --interactive`, or using `git status` to check the staging area while using `git add`. Keeping mental check of it is the worst solution imho. You can also have your git porcelain handle it. Magit for example has a great interactive overview of unstaged and staged changes. When I need to do something more picky than just commiting every change, I'll usually grab magit to stash individual chunks: I don't necessarily want to commit all changes in a file, sometimes I want individual lines. You can do that with staging using the commands above, magit, or some other porcelain (I've heard good things about git kraken). If you really want to forget staging even exists, you could just commit straight up and amend the commit afterwards to get a comparable experience I guess. I've found staging to be helpful in keeping track of what I've achieved for my next "version" of the software to be added to the history, which is why I'm still using it.
- imiric 4y agoGit wasn't the only DVCS with an elegant model. Mercurial, Darcs and Fossil came out around the same time. All are equally elegant in their own ways, and all have a much friendlier UI than Git. So it is possible to have both an elegant implementation, and a friendly UI that doesn't force the user to understand the internals to work with the tool. Git's elegant model is not why it won out. Despite of its shortcomings, I suspect the cult of personality around Linus had a big role in that, as well as major services like GitHub.