https://blog.plover.com/2023/02/27/ The Universe of Discourse Mark Dominus (Tao Mon, 27 Feb 2023 Min Xiu ) mjd@pobox.com I wish people would stop insisting that Git branches are nothing but refs [TOP] I periodically write about Git, and sometimes I say About me something like: RSS Atom Branches are named sequences of commits 12 recent entries and then a bunch of people show up and say "this is wrong, a branch is nothing but a ref". This is More about the true, but only in a very limited and unhelpful way. seventh root of a My description is a more useful approximation to 14-digit number the truth. I wish people would stop Git users think about branches and talk about insisting that branches. The Git documentation talks about Git branches are branches and many of the commands mention branches. nothing but refs Pay attention to what experienced users say about ChatGPT on the branches while using Git, and it will be clear that fifth tarot suit they do not think of branches simply as just refs. American things In that sense, branches do exist: they are part of with our mental model of how the repository works. foreign-language names Are you a Git user who wants to argue about this? This page First ask yourself what we mean when we say "is intentionally your topic branch up to date?" "be sure to fetch left blank? the dev branch" "what branch did I do that work on? ChatGPT on the " "is that commit on the main branch or the dev subject of branch?" "Has that work landed on the main branch?" four-digit "The history splits in two here, and the left numbers branch is Alice's work but the right branch is Uniform Bob's". None of these can be understood if you descriptions of think that a branch is nothing but a ref. All of subspaces of the these examples show that when even the most n-cube sophisticated Git users talk about branches, they Construing cube don't simply mean refs; they mean sequences of faces as pairs of commits. something or other Here's an example from the official Git Math SE report documentation, one of many: "If the upstream branch 2023-02 already contains a change you have made...". There's Finding the no way to understand this if you insist that seventh root of "branch" here means a ref or a single commit. The 19203908986159 current Git documentation contains the word Dog breeds in "branch" over 1400 times. Insisting that "a branch Korean is nothing but a ref" is doing people disservice, Multilingual because they are going to have to unlearn that in transliteration order to understand the documentation. corruption Some unusually dogmatic people might still argue Archive: that a branch is nothing but a ref. "All those people who say those things are wrong," they might 2023: JF say, "even the Git documentation is wrong," 2022: JFMAMJ ignoring the fact that they also say those things. JASOND No, sorry, that is not the way language works. If 2021: JFMAMJ someone claims that a true shoe is is really a JASOND Javanese dish of fried rice and fish cake, and that 2020: JFMAMJ anyone who talks about putting shoes on their feet JASOND is confused or misguided, well, that person is just 2019: JFMAMJ being silly. JASOND 2018: JFMAMJ The reason people say this, the disconnection is JASOND that the Git software doesn't have any formal 2017: JFMAMJ representation of branches. Conceptually, the JASOND branch is there; the git commands just don't 2016: JFMAMJ understand it. This is the most important mismatch JASOND between the conceptual model and what the Git 2015: JFMAMJ software actually does. JASOND 2014: JFMAMJ Usually when a software model doesn't quite match JASOND its domain, we recognize that it's the software 2013: JFMAMJ that is deficient. We say "the software doesn't JASOND represent that concept well" or "the way the 2012: JFMAMJ software deals with that is kind of a hack". We JASOND have a special technical term for it: it's a "leaky 2011: JFMAMJ abstraction". A "leaky abstraction" is when you JASOND ought to be able to ignore the underlying 2010: JFMAMJ implementation, but the implementation doesn't JASOND reflect the model well enough, so you have to think 2009: JFMAMJ about it more than you would like to. JASOND 2008: JFMAMJ When there's a leaky abstraction we don't normally JASOND try to pretend that the software's deficient model 2007: JFMAMJ is actually correct, and that everyone in the world JASOND is confused. So why not just admit what's going on 2006: JFMAMJ here? We all think about branches and talk about JASOND branches, but Git has a leaky abstraction for 2005: OND branches and doesn't handle branches very well. That's all, nothing unusual. Sometimes software isn't perfect. ----------------- Subtopics: When the Git software needs to deal with branches, it has to finesse the issue somehow. For some Mathematics 225 commands, hardly any finesse is required. When you Programming 95 do git log dev to get the history of the dev Language 87 branch, Git starts at the commit named dev and then Miscellaneous 60 works its way back, parent by parent, to all the Book 48 ancestor commits. For history logs, that's exactly Tech 42 what you want! But Git never has to think of the Haskell 33 branch as a single entity; it just thinks of one Oops 30 commit at a time. Etymology 28 Unix 26 When you do git-merge, you might think you're Cosmic Call 25 merging two branches, but again Git can finesse the Physics 21 issue. Git has to look at a little bit of history Law 18 to figure out a merge base, but after that it's not Perl 17 merging two branches at all, it's merging two sets Math SE 16 of changes. Biology 15 In other cases Git uses a ref to indicate the end [mjd-univer] point of the branch (called the 'tip'), and sorta Higher-Order Perl infers the start point from context. For example, Blosxom when you push a branch, you give the software a ref to indicate the end point of the branch, and it Comments disabled infers the start point: the first commit that the remote doesn't have already. When you rebase a branch, you give the software a ref to indicate the end point of the branch, and the software infers the start point, which is the merge-base of the start point and the upstream commit you're rebasing onto. Sometimes this inference goes awry and the software tries to rebase way more than you thought it would: Git's idea of the branch you're rebasing isn't what you expected. That doesn't mean it's right and you're wrong; it's just a miscommunication. And sometimes the mismatch isn't well-disguised. If I'm looking at some commit that was on a branch that was merged to master long ago, what branch was that exactly? There's no way to know, if the ref was deleted. (You can leave a note in the commit message, but that is not conceptually different from leaving a post-it on your monitor.) The best I can do is to start at the current master, work my way back in history until I find the merge point, then study the other commits that are on the same topic branch to try to figure out what was going on. What if I merged some topic branch into master last week, other work landed after that, and now I want to un-merge the topic? Sorry, Git doesn't do that. And why not? Because the software doesn't always understand branches in the way we might like. Not because the question doesn't make sense, just because the software doesn't always do what we want. So yeah, the the software isn't as good as we might like. What software is? But to pretend that the software is right, and that all the defects are actually benefits is a little crazy. It's true that Git implements branches as refs, plus also a nebulous implicit part that varies from command to command. But that's an unfortunate implementation detail, not something we should be committed to. [ Addendum 20230228: Several people have reminded me that the suggestions of the next-to-last paragraph are possible in some other VCSes, such as Mercurial. I meant to mention this, but forgot. Thanks for the reminder. ] [Other articles in category /prog/git] permanent link