This is worth an essay of its own.
This is worth an essay of its own.
To me, the opposite is a more worthy essay: why, with all the power to customize our tech, do we create things that consistently work differently than people's intuition?
The fact that it "mostly jibes" feels like a footgun, not a feature.
I get that for some, "git just works! It made sense from day one" but in my limited experience, 0% of people I've worked with have said that.
Sure, we can all learn the tech. And expert techniques in any field often don't jibe with naive expectations. But for me and the folks I work with, the tech industry feels like it's gliding more towards inscrutible tools vs ease of use.
We've hit a stage where many rely on code completion bots and answer-supplying bots instead of being able to directly embrace our tech. I wish the tech was more approachable on its own, but perhaps this is the natural evolution of things.
There needs to be a balance between creating new, more powerful intuitions, and meeting people at the intuitions they already have.
Case in point, Git's branching model is pretty intuitive when you understand how Linux kernel development works. Perhaps 0% of the people you've worked with have looked into that. That's fine. Different cultures...
Another example that may be worth studying is mathematics and the hard sciences. Learning those is a lot about learning powerful intuitions.
I solve my own problems for my own reasons all the time and therefore other people's intuitions are immaterial in the process. It would just slow me down to think "how would other people use this" when I'm focused on some technical personal problem.
Commercial software developers solve problems with the clear purpose of selling the solution to others and where they know ahead of time roughly what their audience's intuitions are. This is why intuitive GUI applications exist - there are whole industries devoted to finding out what people expect, what lowers cognitive load etc. iOS and Android apps give you a good idea of what is possible with modern tech when the purposes are properly aligned.
The problem here is that git was expressly developed by Linus to solve his own problem in a way that made sense to him with no thought as to how other people would use it. There were no focus groups, early betas, feedback from users and so on. At best there has been slow fixes to the porcelain to fix the stuff that bothers the people who could make a PR to git. On the other hand there are also many front-end projects that attempt to align some other person's idea of how version control is supposed to work with the Git model.
Anyway - I am in the camp where I very seldom get confused about a git thing because the actual expressed model is really simple (in the way that x86 assembly is a "simpler" language than Java). I find most front-ends much more confusing because they don't seem to work the way I expect. But I am never surprised when someone's pet project is understandable only by themselves. Or indeed when a consumer product is consumer-friendly. The real surprise is when a lone programmer makes something for themselves that then goes on to have wide appeal.
> A branch in Git is simply a lightweight movable pointer to one of these commits. The default branch name in Git is master. As you start making commits, you’re given a master branch that points to the last commit you made. Every time you commit, the master branch pointer moves forward automatically.
It has multiple diagrams explaining how commits point to their content and their parents, and branches point to commits. The Pro Git content has been there for at least 10 years (it's what I learned from 10 years ago).
Maybe the problem is just that the Internet is full of blogs that have incorrect diagrams (like those in the OP) and bad explanations, despite the main website having great documentation!
[0] https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-N...
What is your theory about why so many people are having difficulty creating a correct mental model about Git, and why so many people are writing incorrect blogs about it?
If you understand the basic design premise (commits are content-addressed immutable snapshots), the pointer stuff is kind of obvious. It has to work something like that for it to be able to be immutable if you want to be able to make branches/tags after the commit is created.
But I'm not sure git is a case of this. The DVCS that were created following people's intuitions were known to be slow and internally complex, but I have never heard about them failing. (And the slowness is obviously of a kind that can be optimized away.)
We just stuck with the worst UI ever devised in public for a VCS because of network effects.
Not this:
git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] [--no-verify] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]] [--[no-]allow-unrelated-histories] [--[no-]rerere-autoupdate] [-m <msg>] [-F <file>] [--into-name <branch>] [<commit>… ]
Git is not like that. It is very-very simple. If you learn basics of it, your intuition will align with git's "intuition" too, and you can do crazy things with total peace of mind, without googling or looking into source code of git to see how they had to make something "intuitive" in some definition of the word.
Git (and sql) range from simple task to very complicated. Everyone likes to fantasize about making it easier but they’re only thinking about the fraction of functionality they use, rather than everything it currently does.
If someone could come up with a simpler solution they would, but they can’t because git can do extremely complicated things and is internally consistent. Most people underestimate that part
I don't know if this is true of git, but in general we have a disease called, "solving problems we don't have". I don't mean the YAGNI issue, or people trying to talk others out of doing engineering because the current masochistic process is good enough.
I mean the impedance mismatched caused by taking a concrete, physical problem, translating it into a domain that looks nothing like the problem you're meant to solve, and then tweaking how the fiction works so that it fulfills the requirements.
A few wise people have warned me off of this strategy over the years, but there's not nearly enough ink spent on this topic. This impedance mismatch gets worse over time. They asked for X, and you gave them Y, so when they ask to refine X into X + 1, it gets a little harder each time. The complexity goes up and you find confused product owners asking for what should be a simple change and getting tremendous pushback that smells a lot of deflection.
Meanwhile because users think the system works one way, they expect it to behave in certain ways and constantly get rudely surprised by how it actually works.
Again and again in my career, I've found that a lot of performance problems are obscured by accidental complexity and/or X-Y problems, and once you know the task you actually need to perform, and write the code to solve the actual problem instead of an analog, everything becomes clearer. A mix of determinism and pre-determinism (static calculation) makes for a much faster system without sacrificing legibility in the process.
The issue, I think, is that people find the problems they are given to be boring, and so they try to solve an analogous problem they find more entertaining - at first. There are other ways to find joy and fulfillment in simple tasks besides making them into stunts.
Intuition likely comes from how a tree (fir or oak, not binary) is structured. Generally a branch starts at the trunk or some other branch, not at the ground where the trunk gives way to roots.
Intuition is travelling down main path that has branches which diverge and re-merge into the main path.
That's why people seem to intuitively get "merging" back into main, whereas that doesn't generally make sense for physical trees.
The intuition jvns meant is the idea that a branch only constitutes the commits since the point of divergence, but every branch actually contains the full history up to the root of its tree, and `git log` of course shows that. (If you want to only show the commits specific to a branch, you can do `git log parent..branch`. Note also that two branches need not have any common history, it's perfectly possible for a git graph to be disconnected.)
You probably know this, but since we are being pedantic we might as well get it right: That describes "git reset". "git checkout" does that and record that we are tracking branchname. So any commits will move both HEAD and the branchname reference.
cat .git/HEADBut in git, a branch doesn't "contain" anything. It is just a pointer to a single commit. This is completely counterintuitive and makes no sense to most people at first, for a very good reason: the analogy is misleading.
These things shouldn't be called branches. They are pointers: they can be repointed anywhere, dereferenced, and copied by reference.
HEAD is also a stupid term, because it doesn't refer to the head of anything. HEAD is the current pointer, and it can point to any commit, not just the head of a branch. It should be called something like "here". The "detached HEAD" warning is scary and useless.
Just look at these two commands, which do very similar things but look totally different:
git checkout -b staging
git branch -f staging 3d1b582
They are just pointer assignments. Wouldn't it make a lot more sense if they were written like this? git point staging here
git repoint staging 3d1b582