My mental model of a git repo is basically a bramble bush with labels on it.
The bramble stems and branches are the commit history (which may join and well as split, unlike a bramble). The labels are stuck to particular bits of the bramble. Some labels are even stuck to other labels!
You can move the labels around, and you can glue extra bits of bramble to the tips of what you have. You can even hack about with the bramble, but this is not recommended. Label moving often happens automatically, e.g. when 'growing' a bramble tip.
It gets interesting when you compare two brambles (e.g. remote and local repos). You might determine that one bramble is identical to another, just with the labels moved. Or one bramble is the same as the other but with extra stems added. Or both brambles had a common ancestor bramble, but now they both have extra stems. Or perhaps they are completely irreconcilable.
Learning the underlying model behind git is well worth the effort.
For me watching Steve Smith's talk - Knowledge is Power: Getting out of Trouble by Understanding Git - was a lightbulb moment.
I think this is what can confuse people. We have to face the facts that not everyone will need or be able to grok all of what goes on in git and what makes the car go forward. We can all drive that car still!
Take the recursive merging stuff around minute 39. Do I need to know why git's model for merging is so much better and how it works its magic? I don't think so. It's an implementation detail.
Do I need to know how a gearbox works to drive stick shift?
I have never thought of git as a bramble (tree worked fine for me :)) but the thing I always tell people about too is the labels part. What I think is enough for people to realize is that it's just like say SVN or CVS or any other source control mechanism in that there's a tree (bramble) of commits and then every commit can just be pointed to by a label. I can move those labels around any which way I want. Everything else follows from that on a surface level that is the only thing required to work with git in most situations, including some advanced ones.
You don't need to know why certain operations in git are faster, better, have less conflicts or how they work internally. You just need to know what they do and when to apply them.
I don't need to know why I can't make my car start or switch gears without pushing down the clutch. I just need to know when to push the clutch, i.e. if I want to start the car, push it. When I want to switch gears push it (well, mostly, on cars you want to last a while still lol). Of course some people won't even be able to learn how to drive stick shift and can only ever drive automatic.
> Do I need to know how a gearbox works to drive stick shift?
No, but it helps. If I treat my car's powertrain as a black box then it won't be intuitive that:
* I shouldn't slip the clutch to hold my car on an incline.
* Blipping the throttle gives me smoother downshifts.
* Double clutching lets me shift from 2nd to 1st while rolling.
* I can use the engine to slow my descent on longer hills and avoid brake fade
* I should park the car in gear for safety
* etc.
Whether it's better for a given person to memorise that list of facts or to understand the concepts behind them would depend on how much they drive. As a developer I've found it helpful to gain an understanding of the tools I use daily beyond "here's the commands to copy/paste when you want to do xyz".
It may not have sounded like it but I'm actually going to agree with some of this. We might be on a different part of the gradient so to speak. Maybe you can find a good analogy but at least from my point of view the gearbox analogy is falling short now and we'd need a different one or look at git commands one by one :)
Like you say, you can just remember those things. In fact 4 out of those 6 were taught in driving school and you had to remember them. One I only learned because trucks still needed that (double clutching while shifting - not just your case, just in general) but cars didn't when I learned. I personally don't like copy and pasting commands like that but I see a lot of people doing that even for stuff that should be second nature because you need it all the time. I think - to stay in the analogy - for me this is the difference between knowing that I should engine break and how to do it when I want to slow down vs. having a piece of paper in the glove compartment that I pull out and check for what to do and how every time I approach a red light ;)
I'm also someone that likes to get an understanding of the things that I use and do every day. The thing is that there are so many things we use and do all the time that I think (almost) everyone just has to keep a certain level of abstraction away from many things, because there are just so many rabbit holes out there and it's not beneficial for most people to have explored every single rabbit hole all the way to the end (the 'gradient'). Git commit graphs are a DAG and lots of cool things can be done with DAGs, most of which I totally forgot about since I learned about and enjoyed them in university and have never needed them again at that level. It's good to know they exist and be able to dig in when needed/wanted.
You're absolutely right, there are about a million and one rabbit holes you can go down if you _really_ want to understand the tools you use but in the vast majority of those cases you're better off relying on a higher level abstraction.
The interesting part to me of your analogy is that it can demonstrate how having an understanding of what's going on under your layer of abstraction allows you to generalise.
To wring the last bit of life out of the gearbox analogy: if you tell a mechanically inclined driver that blipping the throttle will make their downshifts smoother, they'd hopefully understand how rev matching can be generalised to upshifts too. If you tell a "black box" driver then they probably wouldn't be able to do the same. Of course, the analogy falls apart a bit because understanding rev-matched upshifts isn't particularly useful :)
I've forgotten most of the "advanced" git knowledge I ever learned but I get a lot of value out of the (admittedly not very advanced) understanding that, as you said, commits are a DAG and that branches are just named pointers to nodes on the DAG. That understanding lets me generalise to, for example, backing up a branch (with git branch/tag) before doing a tricky rebase so I can restore it (with git reset --hard) if I need to undo.
I agree that exploring every rabbit hole to the end isn't beneficial - understanding the DAG is typically the only "advanced" git knowledge I need and I've only very rarely had to peel back more layers. I think this:
> It's good to know they exist and be able to dig in when needed/wanted.
is a good way of putting it. My ideal low-level understanding of most tools is knowing just enough that I know what to search for if I ever need to go deeper.
> That understanding lets me generalise to, for example, backing up a branch (with git branch/tag) before doing a tricky rebase so I can restore it (with git reset --hard) if I need to undo.
You can also do `git reflog` on branches to see what they used to point to :)
To a large extent, yes. But when you find yourself stopped at a red light on a steep upgrade, and some idiot behind you decides to wait for the light three inches from your back bumper, things will go better when the light turns green if you have a decent mental model of the physical mechanism of the clutch. Sometimes you want to let those abstractions leak a bit.
I tested a Subaru manual at the dealer a few years back. The exit from the dealership was uphill onto a busy road. So, I stopped and reached for the handbrake.
There was no handbrake.
I managed to work my way back down to the dealership and asked, "Where's the handbrake?"
It turned out that Subaru had decided to replace it with a button and an "automatic" "hill-holder" feature.
Actually you don't need a mental model of the clutch at all for that. You just need to know how to handle steep inclines. There's a technique for that. All you need to know for that is the fact that on a steep incline you will go back a bit until your clutch has a chance to get you moving forward against the hill and that in this case you need to apply that technique. Like knowing when to use rebase, when to use cherry-pick etc. Now why you will roll back on the steep hill is not something a normal operator of a car needs to understand. Neither the clutch part nor the gravity one actually.
Also, if he's literally 3 inches, I would say the best approach is to slowly ease off the brakes until you actually touch the other car but do it so slowly that it's not an impact. All without even pushing the clutch. Then you don't even need to use the brake while pushing the gas pedal trick, because the guy behind you is your brake pedal ;)
For a group of people supposedly primarily in the SV area this is a scary comment thread.
I learned to drive stick in the Bay Area and the way everyone I know there drives stick on an incline is to use the parking brake with a second hand when letting off the brake and letting out the clutch.
Now, when you get good you can stop doing this for most, but for really steep streets (I now live in San Diego and we have a couple; Laurel being one) it’s still an excellent skill to have.
You should go drive a bit in (some parts of) Spain! Not sure if something like this exists where you are.
Imagine: Small towns, really narrow one way streets with foot traffic and underground parking. Getting out of some of those underground car parks is scary stuff!
You get onto a steep incline to get out of the car park but you come around a corner onto that. Cars might be coming down towards you at this point and they're sometimes hard to see. It's cramped too. So you can't just take it w/ speed to get up there. Also on the top you have pedestrians on your side, so you might need to stop on the incline, then when pedestrians have scurried away, go a little further but not directly onto the street until you can actually see if cars are coming. Half your car is still on the incline at that point.
thanks, I'll be watching this. seems like I get myself in trouble every couple of months and have to zip up a directory, do a fresh checkout and overlay it. Seems sometimes something gets lost and it will refuse to push to origin on a branch that I've had checked out for a while. yet if I do a fresh checkout (and losing a bit of history as I like to commit locally a lot and squash just before I'm ready to push to git repo.
Conceptualizing a commit graph with branch/tag labels is the easy part. What gets messy is operations regarding remote vs. local (as you mention) and regarding the various local state one may have (working directory, index/staging). Then there’s also the issues that arise with merging, but you have those with every VCS.
I love mercurial’s solution of having phases for commits. Anything you created locally is Draft phase and can be mutated without “force”. Anything which was pulled or pushed is automatically marked as Public and is not easily mutated. Visualizing the commit graph also colors commits based on phase making it really easy to get a grasp of what’s going on.
Is there an extension or something for Git to have similar behavior to this?
Instead of using colors, a visualization that can be combined with branch colors would be nice. For example using bold for remote (“public”) commits, or dashed lines for local (“draft”) commits.
My mental model of a git repo is basically a stack of backup tapes with sticky notes on them that say “this is tape #2983 and it's almost the same as tape #2429, except that I fixed a typo.” Things like `git log` and common workflows make you think “this is change #2983, where I fixed a typo”, and that's where the trouble starts.
It's an organizational and personal thing, but you really have to get in the habit of treating commits as single diffs to the codebase and not the equivalent of ctrl + s in your editor.
I try and make a habit of squashing my commits so that git log is a narrative of development and each commit is a page number, not a sticky note.
The bramble stems and branches are the commit history (which may join and well as split, unlike a bramble). The labels are stuck to particular bits of the bramble. Some labels are even stuck to other labels!
You can move the labels around, and you can glue extra bits of bramble to the tips of what you have. You can even hack about with the bramble, but this is not recommended. Label moving often happens automatically, e.g. when 'growing' a bramble tip.
It gets interesting when you compare two brambles (e.g. remote and local repos). You might determine that one bramble is identical to another, just with the labels moved. Or one bramble is the same as the other but with extra stems added. Or both brambles had a common ancestor bramble, but now they both have extra stems. Or perhaps they are completely irreconcilable.
Better visualisation tooling would help.