b0rk,
@b0rk@jvns.ca avatar
b0rk,
@b0rk@jvns.ca avatar

got a little grumpy about terminology in this post on HEAD in git https://jvns.ca/blog/2024/03/08/how-head-works-in-git/

stuartmarks,
@stuartmarks@mastodon.social avatar

@b0rk You’re on point here. One criticism of git is that its model is too complex. Even if the complexity is warranted, an issue layered on top of that is inconsistent terminology — it makes the model seem even more complex than it actually is. The uses of HEAD are good examples. Another one is “stage”, “index”, and “cache” which all refer to the same thing.

b0rk, (edited )
@b0rk@jvns.ca avatar

the more I write about git the more I think it's important to be a little critical of git's design and terminology choices when teaching it. A lot of things in git are counterintuitive and it's important for people to know where to be careful.

but it's important to me to be really specific about the critiques, I've heard “the CLI sucks” a million times but I don't find it that helpful.

"here are 12 specific counterintuitive things git does and here's exactly how they work” is much more useful

chx,

@b0rk my favorite counterintuitive thing is git rebase in full format. Like, what do you think git rebase branch1 branch2 even does and how does that differ from git rebase branch1 branch2^0 because they DO differ and significantly so.

The documentation is impossible to find -- it's not in rebase -- https://git-scm.com/docs/gitrevisions#Documentation/gitrevisions.txt-emltrevgtltngtemegemHEADv1510em and also it doesn't help. At all. It's lovely.

simontatham,
@simontatham@hachyderm.io avatar

@b0rk on the other hand, some of the suckiness doesn't really benefit from a conceptual explanation, it just needs memorisation, or aliases, or a cheatsheet. Like the way so many commands spell the 'delete one of these things' option differently, and I don't think there's anything really driving the choices.

git rm
git branch -d
git config --unset
git config --remove-section
git remote remove
git symbolic-ref --delete
git submodule deinit

aadmaa,
@aadmaa@mathstodon.xyz avatar

@simontatham @b0rk It seems like we're stuck with Git in some ways because, you know, it's how all our code is maintained. But has anyone created a wrapper that uses a git service like GH in the backend, but just totally changes the API?

Starting with a CLI that maps a set of commands that actually make sense, to git commands?

jmbuhr,
@jmbuhr@mastodon.online avatar

@aadmaa @simontatham @b0rk One of the co-founders of GitHub is now working on something with a new spin on handling branches: https://gitbutler.com/
It lookes interesting, but I haven't tried it myself, yet.

igrok,

@aadmaa yes, more than once

  • tig
  • Easy Git
  • g2
  • hg-git
  • GitUI
  • jj

(I don't use any of them, but that's what a few minutes of searching turned up)

Then of course there's the GUI clients as well

@simontatham @b0rk

b0rk,
@b0rk@jvns.ca avatar

@igrok @aadmaa i think what jj is doing is pretty interesting, it's early though https://github.com/martinvonz/jj

b0rk,
@b0rk@jvns.ca avatar

@simontatham I'm not sure why but I'm not so bothered by that kind of inconsistency. like it would be good if it were consistent but it doesn't upset me in the same way as some other git design choices

(like the fact that git status says "you are up to date with origin/main" and gives you absolutely no clues at all that "origin/main" itself might be 3 months out of date, you just have to know)

simontatham,
@simontatham@hachyderm.io avatar

@b0rk perhaps because the problems you're talking about cause actual confusion and misunderstanding? The inconsistent spellings of delete (and rename too) are annoying, but you're not confused, you just think 'grr, this one must be spelled another way' and look it up.

And you can be too consistent. svn went the other way, having a uniform set of options for all subcommands. Including 'svn ls -v', using the standard verbose option. My fingers always wanted to type 'ls -l'!

tjc,
@tjc@metalhead.club avatar

@b0rk I think a specific critique I have is that it does not follow the philosophy that there’s only one clear way to do something.

I’ve used git for 14 years and have never once used “git merge”. All you need is rebase. I can’t think of a single reason you’d need git merge if you know git rebase, and if there are cases it’s not clear

b0rk,
@b0rk@jvns.ca avatar

@tjc the situation with merge and rebase is interesting! I've been hearing a lot of “what's the point of merge, all you need is rebase" and “what's the point of rebase, all you need is merge" and "I use both all the time" from different people on here

I think different people have different workflows and, at least with the way git is designed, it makes sense to have both.

(personally I definitely use both merge and rebase pretty regularly for different reasons)

tjc,
@tjc@metalhead.club avatar

@b0rk can you please give an example of something you need merge for that you couldn’t do with rebase? Or do you mean preference?

b0rk,
@b0rk@jvns.ca avatar

@tjc

totally!

  1. create local branch (git checkout -b mybranch)
  2. make some commits on that branch
  3. maybe rebase it onto main a few times
  4. finally it's ready to merge into main and deploy
  5. git checkout main; git merge mybranch; git push origin main

obviously this isn't what you'd do if you're working on a team where you use pull requests and merge them on github/gitlab/etc, but not every repo works like that

vincent,
@vincent@mastodon.coffee avatar

@b0rk Righteous rants like this make me wonder how the universe would be different if Mercurial had launched a week earlier.

b0rk,
@b0rk@jvns.ca avatar
tess,
@tess@mastodon.social avatar

@b0rk you're doing great work with these analyses.

Honestly, I kind of wish someone would put out a version of git that just used consistent terminology and command-line flags; it would still be overly complex for source management but at least it wouldn't also be confusing.

(Like, why does git add -A add everything including unversioned files, but git commit -a only adds modified files? Why is one -A and the other -a, and there's no git add -a or git commit -A?)

b0rk,
@b0rk@jvns.ca avatar

@tess man I'd never realized about this git add -A vs git commit -a discrepancy before, thank you!

heathborders,
@heathborders@hachyderm.io avatar

@b0rk typo:

s/When you do a merge, HEAD in the merge conflict is the same as what HEAD when you ran git merge. Simple./When you do a merge, HEAD in the merge conflict is the same as what HEAD was when you ran git merge. Simple./

b0rk,
@b0rk@jvns.ca avatar

@heathborders fixed, thanks!

levitte,
@levitte@mastodon.nu avatar

@b0rk
Really good essay, and it confirmed the few last bits I had questions on (so by now, I feel 100% confident 😉)

b0rk,
@b0rk@jvns.ca avatar

@levitte that's the dream :)

ednl,
@ednl@mastodon.social avatar

@b0rk Excellent reference, thanks. This needs +was: "When you do a merge, HEAD in the merge conflict is the same as what HEAD when you ran git merge."

I am not sure what the second line means here:

  • commit 96fa6899ea (HEAD -> main)
  • commit 96fa6899ea (HEAD, main)
    If that is your current commit, and HEAD, and main, then how can HEAD not point to main like in the first line? Does it mean that you're on a different branch than main? But then shouldn't that other branch be listed too?
b0rk,
@b0rk@jvns.ca avatar

@ednl it means that HEAD points directly to the commit 96fa6899ea instead of pointing to the branch main. does that make sense?

ednl,
@ednl@mastodon.social avatar

@b0rk Not quite, sorry. You say on the blog that eveything in parentheses points to the commit. So HEAD points to the commit (directly) but main also points to the commit (i.e. the commit is part of the main branch?). But I don't understand how that is different from the first line where HEAD "is on main" as indicated by the arrow, and that combination points to this commit. Maybe this is too esoteric and minor, sorry!

b0rk,
@b0rk@jvns.ca avatar

@ednl in situation 1, .git/HEAD contains the string ref: refs/heads/main and .git/refs/heads/main contains the string “96fa6899ea”

in situation 2, .git/HEAD contains the string “96fa6899ea”

in situation 3, .git/HEAD contains the string "96fa6899ea" and .git/refs/heads/main is some other commit

ednl,
@ednl@mastodon.social avatar

@b0rk Thank you for indulging me. Yes, that makes it more tangible to me. I think my confusion was born from my idea that a branch is a history of commits, where in fact it is also just one pointer to one commit (which then has 'parent' or 'prev' refs, I presume).

So the first and second situation are effectively the same where the only difference is that HEAD is an indirect pointer in 1 and a direct pointer in 2, but in both 1 and 2 'main' points this commit in the same way.

b0rk,
@b0rk@jvns.ca avatar

@ednl yeah exactly. it's a really important difference though because in situation 2 your HEAD is "detached" and so any commits you make will be orphaned

ednl,
@ednl@mastodon.social avatar

@b0rk Ah yes. Then the most confusing part to me is that Git chooses to display 'main' for this commit, presumably because it is in the history of the main branch. But it's not the actual latest main pointer?

EDIT: or it is, and we got here via a really convoluted way e.g. by checking out a prev commit and then the next one again?!

I guess I just never noticed this or registered it whenever I happened to be in detached head state, because I always try to get out of it as quickly as possible.

b0rk,
@b0rk@jvns.ca avatar

@ednl it is the actual latest main pointer

b0rk,
@b0rk@jvns.ca avatar

@ednl (really appreciate your question, thanks for asking it! updated the post to try to clarify)

mwop,
@mwop@phpc.social avatar

@b0rk That was SUPER interesting to read! Thanks!

neilk,
@neilk@xoxo.zone avatar

@b0rk
> Similarly, the meaning of “ours” and “theirs” are flipped in a merge and rebase.

🤯.

I’ve been advocating rebase over merge for years, but had also concluded I have no idea what “ours” and “theirs” actually mean and now I know why!!

b0rk,
@b0rk@jvns.ca avatar

@neilk I just learned this recently too and I was honestly shocked

meejah,
@meejah@mastodon.social avatar

@b0rk I have done "git checkout <tag>" before for use-cases like "there's a bug on <tag>" so you check out the tag, confirm "yes, that's indeed a bug" and can then re-create a working branch for that release tree (e.g. "git checkout -b <tag + 0.1>" or similar).

b0rk,
@b0rk@jvns.ca avatar

@meejah are you doing git checkout v0.1 or git checkout refs/tags/v0.1? I'm specifically curious about the refs/tags usage

meejah, (edited )
@meejah@mastodon.social avatar

@b0rk ...but also I would assume those are the same thing, but given "it's git" and you clarified I'm assuming "nah, they're different" 🤔

b0rk,
@b0rk@jvns.ca avatar

@meejah yeah they're different for some reason but I have no idea what the use case is for git checkout refs/tags/v0.1

tedmielczarek,
@tedmielczarek@mastodon.social avatar

@b0rk @meejah I can only assume it's just git being built out of a set of primitives, and since a ref is an arbitrary label for a commit it's a thing that you could do.

b0rk,
@b0rk@jvns.ca avatar

@tedmielczarek @meejah oh never mind, I was wrong about how this works and just got misled by my git prompt being weird

meejah,
@meejah@mastodon.social avatar

@b0rk Oh, I see ... yeah I think I've only ever done the former thing.

Luckily, I just use simpler branching / releasing flows for all "my" things these days ;) so it has been a while...

erewok,

@b0rk This is great. (Looks like maybe a very minor typo near the top: "ref: refs/heads/meain")

b0rk,
@b0rk@jvns.ca avatar

@erewok fixed, thanks!

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • Durango
  • DreamBathrooms
  • khanakhh
  • GTA5RPClips
  • osvaldo12
  • magazineikmin
  • mdbf
  • InstantRegret
  • rosin
  • Youngstown
  • slotface
  • everett
  • kavyap
  • ngwrru68w68
  • megavids
  • modclub
  • tester
  • tacticalgear
  • cubers
  • thenastyranch
  • cisconetworking
  • ethstaker
  • Leos
  • provamag3
  • normalnudes
  • anitta
  • JUstTest
  • lostlight
  • All magazines