Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>(This should perhaps be a comment but it's way too too big and needs nice formatting :-) ... also, I appear to be in a quirky mood, if you follow some of the links...)</p> <p>The key to understanding this—I think you're already there, but let's put this in the SO article to make it clear to the next reader—is this:</p> <p><strong>All git refs wind up naming (pointing to) a single commit.</strong></p> <p>This is true for tags (whether lightweight or annotated), branches, "remote branches", git "notes" references, the "stash", and so on. They all name one commit, and that's it. (Well, OK, not quite: technically, tags can name any object in the repo. In fact, that's how annotated tags work: there's a lightweight tag that names a repository object that <em>is</em> the annotated tag, and then the annotated tag names a commit object. That's also how <code>HEAD</code> works: it usually names another ref, which then names the commit. So, sometimes you have to peel a few layers off the onion to hit the commit. Naming a blob or tree object is possible, but normally, nothing actually does this.)</p> <p>(The "true name" of the commit is, of course, the SHA-1 value.)</p> <p>What makes a branch reference name "special" is equally simple:</p> <p><strong>A branch reference is a name that automatically moves to the new branch tip, when new commits are added.</strong></p> <p>Specifically, a ref of the form <code>refs/heads/<em>branchname</em></code> points to some commit (by definition, since names point to commits). When you are "on" that branch<sup>1</sup> and do some git operation that adds a <em>new</em> commit, like <code>git commit</code> or <code>git merge</code> or <code>git cherry-pick</code>, git sticks the new commit into the repo, then re-points the name to the new commit. That's all it has to do!</p> <p>What we think of as "the branch" is formed by starting at the tip—the commit to which the name points—and working backwards, using each commit's parent or parents. If the commit has one parent, it's an ordinary commit "on the branch". If it has two or more, it's a "merge", and you can follow all of its parents to find what got merged. If it has no parents at all, it's a root commit (like the initial commit in a new repo—you can actually have more than one root; git "notes" do this, for instance).</p> <p>If you put seven branch labels onto one commit, you now have seven<sup>2</sup> names for "the branch". If you clear this down to one, it's <a href="http://www.jabberwocky.com/carroll/walrus.html" rel="nofollow">less confusing</a>, of course, but git won't care either way. (Git only cares if you take it down to zero names. Now the branch still exists, but it's really hard to find, and it's eligible for <a href="https://www.kernel.org/pub/software/scm/git/docs/git-gc.html" rel="nofollow">garbage</a> <a href="http://www.albanyny.gov/_images_content/Government/Departments/GeneralServices/TrashAndRecycling/Trash%20Collection029.JPG" rel="nofollow">collection</a>.)</p> <p>Since we're on the topic, let's also make a note about "<a href="http://thumbs.dreamstime.com/z/remote-control-3d-glasses-tv-movie-dog-27254213.jpg" rel="nofollow">remote</a> branches". (I have never been quite satisfied with the name "remote branch" but I don't have a better one, so let's just define it.) A "remote branch" is a <em>local</em> ref of the form <code>refs/remotes/<em>rname</em>/<i>bname</i></code>, where <em>rname</em> is the name of the remote (such as <code>origin</code>) and <em>bname</em> is the branch name on the remote, i.e., the part that comes after <code>refs/heads/</code> if you log in on that remote and look at the branch over there. You can't get "on" a remote branch—if you <code>git checkout origin/master</code>, git gives you a <a href="http://en.wikipedia.org/wiki/Guillotine" rel="nofollow">"detached HEAD"</a>—but these branch names <em>are</em> automatically updated: when you use <code>git fetch</code> to get new commits from the remote, you also pick up the new branch-tips. In other words, instead of <em>you</em> moving the names to the new branch tips, you let someone else do it (on the remote) and then you pick up their latest version all at once, when you fetch from them.</p> <hr> <p><sup>1</sup>To be "on a branch", the <code>HEAD</code> ref must be an "indirect" reference, something like <code>ref: refs/heads/master</code>. When <code>HEAD</code> is instead "detached" it contains a raw SHA-1 value. You can still add commits; they're added to an un-labeled branch. The reference in <code>HEAD</code> keeps them from being garbage-collected.</p> <p><sup>2</sup>Or more, if there are tags. Let's assume there are <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/13/No_tags.svg/320px-No_tags.svg.png" rel="nofollow">no tags</a>.</p> <p><sup>3</sup>There is no footnote three.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload