Live data from Hacker News

Git Branches: Intuition and Reality

jvns.ca

61–70 of 281 posts

Re: Git Branches: Intuition and Reality

#61
post #27

> in general, even if people’s intuition about a topic is technically incorrect in some ways, people usually have the intuition they do for very legitimate reasons! This is worth an essay of its own.

I guess. 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 te…

You do have a point, but it's not a slam dunk. Intuition isn't some fixed thing but arises from personal experience. A lot of that is common to a culture, but there are different cultures and in any case, some truly personal aspects remain.

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.

Re: Git Branches: Intuition and Reality

#62
post #3

I cannot be the only one that gets away with only knowing: git pull git merge x git checkout [-b] foo git commit git push

You’re definitely not the only one, but you will level up if you learn branching. After that you can become the guru amongst your peers and a god among men if you learn how to use ‘git reflog’. ;) That will help you learn how fix almost any git accident.

Re: Git Branches: Intuition and Reality

#63
post #22

Earlier quoted context omitted.

I'm still missing what part of the intuition is incorrect? It seems like the only "incorrectness" is that there's no explicit hierarchy of branches. Except that's wrong the HEAD ref points to the default branch. Any other branches are of equal significance, though.

Intuition would be that the branch starts at the point that it diverges from main, labeled “base” in the first diagram. In reality, the first commit in “main” and “branch” are the same commit. 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.

I don't agree with the author here.

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.

Re: Git Branches: Intuition and Reality

#64
post #38

Earlier quoted context omitted.

"THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE." I will keep using them so I can keep using old software. How new is it? Does ubuntu or debian have it?

They have been introduced in git 2.23 released in august 2019.

And is in Ubuntu 22.04 and Debian 11.

Re: Git Branches: Intuition and Reality

#65
tl;dr Please ignore, just me working through a Python+pygit2 problem. I solved it in a grandchild comment.

I had so much trouble trying to map my intuited/mental model of git onto pygit2 that I gave up and just used the git module.

I wanted to automate a fairly simple thing in Python as opposed to bash+commands. My reasoning being that I wanted to do it "right" and be a Big Programmer Real Boy(tm). I just wanted to create a branch remotely in Github, pull the repo, and checkout the new branch. I got stuck going in circles trying to figure out why I was always left in detached HEAD state because I didn't understand exactly what git was doing during a checkout.

    # repo has already been pulled
    if os.path.exists(repo_path):
        local_repo = git.Repo(path=repo_path)
        self.log.debug(f"current branch: {local_repo.active_branch.name}")
        local_repo.git.checkout(branch_name)
That's super easy and is much the same as running the commands in the shell or in a bash script.

Of course, I've lost my poor implementation using pygit2, so I'll add that later if I find it. Thankfully there's a good discussion surrounding the issue I encountered in this excellent "roll your own git in Python", which doesn't use pygit2, but the concepts are the same: https://www.leshenko.net/p/ugit/#checkout-switch-branches

Re: Git Branches: Intuition and Reality

#66
post #8

A lot of things in git are just pointers to commits, and then the git implementation handles them under the covers in some way that usually makes sense but not always. One example that also bites people: moving files isn't stored in git - if you move files (even with `git mv`) and create a new commit, the moves aren't stored, but this is reconstructed later by the client based on similarity, which comes from the diff…

Yup. “Storing moves” is the kind of thing that might sound intuitively obvious but then gets gnarly and non-obvious when you think about it for five minutes. And so something that might be “obvious” to do then turns out to be so non-obvious—how to catch all file moves (intent) outside of simple identitical content cases, and how do you represent them internally?—that you realize that just using snapshots is really th…

It’s completely trivial. The obvious and correct place is in the commit object just like author and date and such, since renaming is semantically part of the commit, not the tree:

  commit 0123456789abcdef0123456789abcdef01234567
  parent fedcba9876543210fedcba9876543210fedcba98
  author Nemo  1234567890 +0000
  committer Nemo  1234567890 +0000
  rename-from path1.old
  rename-to path1.new
  rename-from path2.old
  rename-to path2.new

  Commit message
And you don’t detect moves (because that’s madness), but require that people record them deliberately, just like every other VCS has done. There’s even git-mv already, it just skips a step that every other VCS’s equivalent command would do. (And technically this all works out because the index is a commit, so you can record the rename normally.)

Of course, all of this assumes that moving a file is a meaningful operation. Perhaps ideally (for most languages and systems) you’d track this in far smaller chunks, so that you can track changes to a function even when it alone was moved to a different file. But things like Git aren’t interested in those kinds of semantics, and work technically at the file level, more or less, so I think it should track renames because in practice straightforward renames are super common, but often also involve other changes that thwart rename detection. Years ago Linus explained why he didn’t like storing moves (someone else has linked it), but I’m largely not sold with his reasoning—the theory of the perfect has hindered the useful, and file renames are commonly meaningful in ways more than he said.

Re: Git Branches: Intuition and Reality

#67
post #8

A lot of things in git are just pointers to commits, and then the git implementation handles them under the covers in some way that usually makes sense but not always. One example that also bites people: moving files isn't stored in git - if you move files (even with `git mv`) and create a new commit, the moves aren't stored, but this is reconstructed later by the client based on similarity, which comes from the diff…

> moving files isn't stored in git is there an intuitive and enlightening explanation as to why it is this way?

Git doesn't store any individual changes: files moved, lines added, line deleted, etc.

It stores a commit graph, and a tree at each of those commits. (A lossless compression algorithm deduplicates information.)

There's no need for the author to be concerned with what diffing information gets incorporated into the commit. Diffs are up to the viewer of the commit history.

  git show --diff-algorithm=...

Re: Git Branches: Intuition and Reality

#68
post #3

I cannot be the only one that gets away with only knowing: git pull git merge x git checkout [-b] foo git commit git push

you're def not the only one. but learning more pays dividends in confidence and resilience. fyi, pull is just shorthand for fetch && merge

Re: Git Branches: Intuition and Reality

#69

Lately I’ve wanted branches (heads) to have a corresponding tail which points to the base commit that the branch sits on top of (like the commit on `main` when you created the branch).[1] Because branches get rebased all the time and eventually you have six commits out in the Æther somewhere and you have to think twice about where it even starts. And yeah you can probably think for a few seconds and recall that you h…

It looks like this is what git merge-base --fork-point is supposed to do, although according to the docs it is not 100% reliable.

Re: Git Branches: Intuition and Reality

#70
post #26
post #3

I cannot be the only one that gets away with only knowing: git pull git merge x git checkout [-b] foo git commit git push

For me, git becomes unintelligible when there's a crazy train-track map of branching and merging. So I usually do whatever I can to keep a single straight-line master history. I branch off for a task, then after a while my branch isn't joined at the tip of master. So I rebase locally until it is. Then when the PR happens, master gets my changes added to the top, with no extra noise from merge commits. Even if the loc…

I think this is a pretty sensible approach. Git feels like one of those tools where you are given a lot of power but it's your responsibility to use it in a sensible way. A bit like with Excel or spreadsheets. You can do a lot but you can also make a big mess pretty quickly.
Post reply on HN