Ron Garret <ron1@xxxxxxxxxxx> writes: >> For my rather fresh eye it looks more like unnamed (anonymous?) branch >> than a temporary one. Doesn't detached HEAD behave exactly like a >> regular HEAD but pointing to the tip of an unnamed branch? > > I strongly concur with this. > > And as long as I'm weighing in, it would also help to prevent confusion > if it were made clear that this unnamed branch doesn't actually come > into existence unless and until you do a commit. After re-reading this three times, I actually cannot tell which one you think is the confused misconception: (1) unnamed branch does not exist until you commit, or (2) unnamed branch does exist immediately you detach. Let's say you have this history: ---A---B HEAD == master When drawing commit ancestry in ASCII art, uppercase letters in the drawing denote commits. Time flows from left to right and we don't write arrows to show B is a child of A. On the right, above or below commit, we also write refs (i.e. tags, branches and HEAD). When we say "HEAD == master", we mean HEAD is a symref to master ref (if we really want to be anal, 'refs/heads/master' might be more technically correct but most often it is clear from the context). So by the above picture, we mean "There is a history that ends with B, whose parent is A and it came from somewhere. 'master' branch points at B and HEAD symref points at 'master' so that is the current branch". Here is what happens when you make changes and "git commit" it. (0) Normal case. ---A---B---C HEAD == master The new state is recorded as a tree, a new commit C is created to wrap that tree, C is made a child of B (because HEAD pointed at it), and finally, master is moved to point at that commit C (because HEAD pointed at 'master'). Notice that two "HEAD pointed at" mean slightly different things in the above sentence. In the former context of determining the commit to become the parent of a new commit, we want commit, and "evaluating HEAD by checking at what it points at" wants to return commit, so even though technically HEAD at this point would be: $ cat .git/HEAD ref: refs/heads/master" IOW, it points at 'master' branch, we look beyond it and talk about the commit that is pointed at refs/heads/master. In the latter, we want to determine if there is a branch we would want to update to point at the newly created commit, so we look at HEAD and notice it points at refs/heads/master. We update it, instead of storing the value of C directly in HEAD. Now, "git checkout master^0" would do this: ---A---B---C HEAD (detached) master There are two pointers. $ cat .git/HEAD 562d53fa69933b3ade2691b99cbe67722313f43c $ cat .git/refs/heads/master 562d53fa69933b3ade2691b99cbe67722313f43c They point at the same commit C (let's pretend 562d53... is C). You make changes and create a commit. What happens? (1) A new tree is created and wrapped in a new commit D, whose parent is C. D we have not updated / any ref yet ---A---B---C We used the fact that HEAD points at C (in the first "what commit is pointed?" sense) to determine the parent of D. (2) We decide what pointer to move to point at this commit. HEAD does not point at any branch (it directly pointed at commit C), so we do not move any named branch, but move only HEAD. The end result is: D HEAD (detached) / ---A---B---C master Now you then do "git checkout -b side". What happens? (3) We create a new branch "side" at the commit HEAD points at (we could have said "git checkout -b side HEAD"), and make HEAD point at that branch. D HEAD == side / ---A---B---C master Now, when we say "branch", we do not mean the "line" between C and D. "master" branch is not a line before A, between A and B and between B and C concatenated together. "master branch" in git simply points at C in the above graph. Especailly, there is no special "master"-ness to the line between B and C. B can be reached from both 'master' and 'side' branches. A corollary is that a line between C and D does not have any special 'side'-ness either, as later you can fork other branches from D. Similarly, in picture (2) where HEAD is still detached, there is no special 'HEAD'-ness to the line between C and D. Similarly in the picture where you had HEAD that was detached that pointed at C: ---A---B---C HEAD (detached) there is no HEAD-ness in any of the line segment depicted. The same goes for all the lines depicted in picture (2); between these two pictures, the only change made was a commit on the detached HEAD. From the perspective of "branches", there is no change. Calling detached HEAD as "temporary" or "anonymous" branch is fine, but then we should consider the state immediately after detaching the HEAD equally valid "anonymous" branch as in picture (2). Putting it in another way, a branch in git is _not_ the name given to line segments that _led_ to the point the branch points at (i.e. past history). Think of a branch as the point where your next commit advances from (i.e. future history). -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html