4 ms·
A git branch is a pointer. It can point at whatever. This shouldn't be confusing, but it is because that's not a natural way to think about revision control, s
by Espressosaurus 3y ago
A git branch is a pointer. It can point at whatever.
This shouldn't be confusing, but it is because that's not a natural way to think about revision control, so we instead have to relitigate it all the time for people that haven't learned git's obtuse naming conventions.
- Buttons840 3y agoIt seems like the natural way to me. What do you think the natural way is?
- Espressosaurus 3y ago> It seems like the natural way to me. What do you think the natural way is? A branch is a DAG of commits terminating at one commit. They should have just called it a pointer if it's a pointer. But here we are anyway.
- lakpan 3y agoThat’s not right. A branch is a single pointer to a single commit. Just open your .git folder. It’s then Git itself that follows that commit’s pointer to its parent(s). The branch, like the tag, is a single reference to a commit. Do this: $ cat .git/refs/heads/main
- Buttons840 3y agoIt seems accurate enough to say the branch includes all the parents of the pointed to commit. It's a matter of definition, but both definitions are technically accurate. (Also, note the path you ask us to cat does not contain the word "branch". You refer to how things are stored to support your definition, but the way things are stored doesn't use the term "branch".)
- Espressosaurus 3y agoThe question was "what do you think is the most natural way to think about it", not "how does git represent it".
- lakpan 3y agoWhat? If you’re looking for “the most natural” then you’ll find it in the name. You can’t “explain” branch by using a synonym. Plus that definition describes both tags and branches, how do you tell them apart? It’s clearly lacking. Actually that definition fits commits too. I’d rather use these: Branch: a pointer that advances Tag: a permanent pointer Commit/hash: an even more permanent pointer (because even a force can’t change it) that also describes the changes.
- seba_dos1 3y agoTechnically, you're right. Practically however, it does make sense to implicitly dereference the branch you're talking about to the commit it points to. Asking "is this commit on that branch?" is semantically equivalent to "is this commit reachable from the commit that branch points to?". That said, it only makes sense to make such implicit mental shortcuts once you're already comfortable with git's data model. If you're not and you're still learning it, it's only going to confuse you.
- lakpan 3y agoTo be honest, describing a branch the wrong way is only going to confuse people more. The “dots on the line” visualization is pretty clear: you can have any number of branches pointing to a specific dot/commit. How do you add “branches” without fundamentally breaking that concept? When you create a branch, you’re not copying the line, you’re just adding a pointer.
- Buttons840 3y agoAre you saying that the "natural way" you think about branches is as a DAG terminating at one point? Because that is true; that is accurate. Thus, I don't understand your original claim that branches work in an unintuitive way.
- Espressosaurus 3y agoA branch in Git is just the pointer to the tip of the DAG. The way I find it natural to think about is it's the entire DAG of commits. To put this in programming terms, a git branch is a pointer. I think of a branch as the value is the most natural way to think about it. This mismatch is what leads to endless tutorials on what git actually means when it uses its vocabulary.
- Buttons840 3y agoIf I created my own git implementation with the exact same CLI, but under the hood I didn't use a "pointer", but instead used the "value", would this be more intuitive to you? One problem I'm trying to express with that question is: You say it's unintuitive, but when asked why you refer to a very low level technical detail. My suspicion is that people find git branches unintuitive, and thus they think something more intuitive must exist. They have vague ideas about what "more intuitive" might mean, usually it means "just do what I want in this one situation I'm currently facing". My theory is that, if pressed, nobody can fully define a behavior for branches that is more intuitive than the current git implementation.
- Espressosaurus 3y agoWell, you're still using the same CLI which is part of the problem. Git's CLI reflects its patched-together-hacked-executable history. It shouldn't be controversial to say the porcelain can and should be much more straightforward to use. DVCS concepts like the DAG and where you want to apply diffs are complicated the first time around, but after you get the concepts it should be easy to use, not difficult. Mercurial's branches are a better match for how I've seen branches use in practice. Tags are essentially the same between both. Evolve's hidden commits make it easier to recover lost data than Git's reflog, though the underlying implementation not permitting garbage collection kind of sucks.
- cryptonector 3y ago> A branch is a DAG of commits terminating at one commit. [Pedantically] this includes orphaned branches. > They should have just called it a pointer if it's a pointer. A branch in every VCS is first and foremost a name. That name has to evaluate to a) content, b) history. In Git and Git-like immutable-commit systems this can trivially be implemented by a table mapping branch (and tag and...) names to commits. I.e., in any immutable-commit VCS branches are naturally pointers. The only real question is whether there should be additional semantics layered upon the pointer nature of branches. Indeed, there should be. In Git these are the basic rules: - branch names are updated when adding commits in a workspace that has that branch checked out - tag names are NOT updated when adding commits when adding commits in a workspace that has that tag checked out - local configuration can enforce a variety of rules via commit hooks - upstreams can enforce a variety of rules, such as fast-forward-only (no history rewriting) This gives users a great deal of flexibility, including the ability to ban history rewriting on published branches and to allow it on unpublished branches.
- delecti 3y agoI think the most intuitive way to think about commits in a version control system is that they would be diffs. It's certainly how most people interact with git. Even despite knowing that's not how they work in git, it's usually easier for me to treat them that way.
- cryptonector 3y agoThe appearance that commits are diffs is realistic enough though. The question was why branches (and tags, and other refs) as pointers is unnatural, and I second the question because for me it's quite natural, while Mercurial style branches feel quite restrictive (and I never internalized their rules).
- bee_rider 3y agoThe fact that it can point to anything seems a little bit confusing. For example, when I was first learning about git, I decided for some silly reason to make a git repo to store all of my little experiments—20 lines of python or matlab type stuff—just to have them all in one place. The main branch basically just has a README to remind me why the directory is empty, and to look at the other branches. This is a very silly way to use git, I think, because they aren’t really branches of one coherent project. Diffing and merging them is useless. If they produce temporary output files, they all do it in totally non-standard ways that have no relation to one another. There really is no value to collecting them together. But it is possible, of course, because git can point to anything! Thankfully it is hiding on my hard-drive, hopefully nobody will ever see it other than me.
- cesarb 3y agoThat's more common than you think, because GitHub has the magic gh-pages branch which is used to publish to GitHub pages; that branch usually has no commits in common with the master branch.
- withinboredom 3y agoBack when GitHub had a “maximum number of repositories” limit, and a project was done. We copied all commits from the done project to a branch on a “graveyard” repository. All branches were 100% unrelated to each other.
- MatthiasPortzel 3y agoThe problem is that we, both people using git and teaching git, constantly say thing like “a commit is on this branch” or “we need to merge these branches” or even in the OP zine “you can remove commits from a branch.” All of these phrases reinforce the common misconception that branches are “containers” for commits. It would seem that you could query, “oh, what branch is this commit on?” But that’s not how git works. A commit has no idea what branch it is on, and that’s unintuitive. The only definition of being “on a branch” is, starting at the commit that the branch is currently pointing to, all ancestors of that commit are on the branch.
- rmwaite 3y agoI don't think it is inaccurate to say that a branch is a "container" for commits because a branch by definition points to a commit that has zero or more parent commits. Having to walk the commit ancestry to see if a commit is on a branch doesn't make it not true.
- forrestthewoods 3y agoIt’s confusing because that pointer moves all over the place all the time in different ways. Sometimes the pointer moves when you perform other actions. Sometimes you want the pointer to move but it doesn’t. The concept “a branch is a pointer” isn’t a confusing. However the practice of managing and predicting the behavior that pointer is complex, error prone, and full of nasty edge cases.
- Buttons840 3y agoI can see how that is confusing at first glance, maybe. I think people want branches to just do what they want. They complain that branches are confusing, but if you ask them to define how a branch should work, they won't have a complete answer.
- forrestthewoods 3y agoSure. They won’t have a complete answer BECAUSE ITS CONFUSING. If people could give a complete and detailed answer then they wouldn’t be confused, by strict definition! There’s two problems here. One, branch tag behavior is genuinely confusing. Two, branch tags are intrinsically complex (which is why they’re confusing). Git is intrinsically complex. Version control is a hard, complex problem! Pretending that it isn’t complex just results in a lot of confused users and a lot of unhelpful people who think if they yell “it’s actually simple” just a few more times everything will be ok.
- Buttons840 3y agoThe big question is, can we find a more intuitive interface? I think git is pretty close to the most intuitive interface possible, but the problem git solves is hard, as you say. Even the best interface, programmed by God, might not make this easy.
- Espressosaurus 3y agoGit is one of the worst interfaces possible. The underlying implementation is fine, but far too much of the plumbing is visible as porcelain. Mercurial has about as intuitive an interface as is possible IMO. There's still all the intrinsic complexity of distributed version control, but the verbs are meaningful and if I don't know how to do something, knowing the verb is sufficient to use the built-in help to learn how to do the thing I want to do. The concept of branches as the entire DAG and not just a commit also better matches how I've seen version control workflows be used in practice across multiple teams and companies. Add in rewriteable history, like what Git allows or Evolve enables, and you're golden.
- dessimus 3y ago>A git branch is a pointer. It can point at whatever. Not really, a branch is only a pointer to a commit, not to trees or blobs. The commit in turn points to 1 or more parents (unless its the root-commit) and to the tree object that represents the state of the workspace at the time commit and contains pointers to blobs (files) and other trees (subdirectories).