186

When you run git branch -r why the blazes does it list origin/HEAD? For example, there's a remote repo on GitHub, say, with two branches: master and awesome-feature. If I do git clone to grab it and then go into my new directory and list the branches, I see this:

$ git branch -r
origin/HEAD
origin/master
origin/awesome-feature

Or whatever order it would be in (alpha? I'm faking this example to keep the identity of an innocent repo secret). So what's the HEAD business? Is it what the last person to push had their HEAD pointed at when they pushed? Won't that always be whatever it was they pushed? HEADs move around... why do I care what someone's HEAD pointed at on another machine?

I'm just getting a handle on remote tracking and such, so this is one lingering confusion. Thanks!

EDIT: I was under the impression that dedicated remote repos (like GitHub where no one will ssh in and work on that code, but only pull or push, etc) didn't and shouldn't have a HEAD because there was, basically, no working copy. Not so?

Ben Hamill
  • 2,661
  • 2
  • 19
  • 18

7 Answers7

166

@robinst is correct.

In git, you can select which branch is checked out by default (i.e. when you clone). By default, origin/HEAD will point at that.

On GitHub, You can change this in the Admin settings for your GitHub repo. You can also do it from the command-line via

git remote set-head origin trunk

or delete it altogether via

git remote set-head origin -d

Example. Look at the 'Switch Branches' drop-down. trunk is checked, so origin/HEAD follows trunk.

cdunn2001
  • 17,657
  • 8
  • 55
  • 45
  • I renamed another remote to be `origin` and my `otherremote/HEAD -> master` was bothering me. Running your command fixed that for me. – Felipe Alvarez Jun 16 '17 at 05:48
  • I guess what's confusing about this is that it seems like in this case, `HEAD` is pointing to an entire branch, while in a local clone it's going to be pointing to a specific commit... is that wrong? – Stephen Oct 04 '22 at 17:17
  • To try to answer my own question, from this answer (https://stackoverflow.com/a/8841024/783314) it seems that the remote HEAD does actually point to a commit (perhaps the latest in its branch? just guessing) even though in practice it's used for determining the default branch (https://superuser.com/a/1192881/96618 is also useful). – Stephen Oct 04 '22 at 17:28
69

The reason a bare repository can have a HEAD, is that because it determines which branch is initially checked out after a clone of the repository.

Normally, HEAD points to master, and that is the branch that is checked out when people clone the repository. Setting it to another branch (by editing HEAD in the bare repository) results in that branch being checked out on clone.

robinst
  • 30,027
  • 10
  • 102
  • 108
  • 2
    Because it is possible to remove this reference without pushing, `origin/HEAD` is a local reference correct? Does removing it have any affect on `origin`? – Zach Olivare Jan 03 '16 at 03:55
  • @zposten: No, in the same way that deleting `origin/master` doesn't affect the remote. – robinst Jan 05 '16 at 08:03
  • That would mean that after cloning the reference is just a useless piece of information. – Bachsau Jun 17 '19 at 11:14
  • @Bachsau the reference doesn't get cloned. – robinst Jul 01 '19 at 00:57
  • For anybody who is confused like I was, in the above answer you can replace "bare repository" with "GitHub or similar remote repository" to get roughly the intended meaning. I wasn't sure why it would be considered "bare" and it turns out that that's a big topic of its own (google "git bare repository" for more...). – Stephen Oct 04 '22 at 17:02
29

I was under the impression that dedicated remote repos (like GitHub where no one will ssh in and work on that code, but only pull or push, etc) didn't and shouldn't have a HEAD because there was, basically, no working copy. Not so?

I had the exact same impression like you said.

And I even can not delete that origin/HEAD remote-tracking branch cloned from github by doing

git branch -d -r origin/HEAD

This had no effect.

Can some one tell me how I can delete that origin/HEAD remote-tracking branch?

update

Though I did not found why there is a origin/HEAD created when clone from github, I find a way to delete it.

The new version of git provide

git remote set-head <name> -d

to delete the useless HEAD pointer of remote-tracking branch.

And we can also change the dumb default name 'origin' to whatever we want by using

git remote rename origin <new_name>

Hope this can help. :)

Community
  • 1
  • 1
boblu
  • 466
  • 6
  • 11
13

You're right that pushing to dedicated remote repos work much better when they are 'bare', that is, when they don't have working directories. Git's architecture is designed for updating by patches or pull (fetch), which makes sense in a distributed VCS. As the docs say somewhere, pushing to a branch which is currently checked out can result in "unexpected results".

The HEAD is part of the requirements for a valid repository. Git Repository Layout says, in part:

HEAD

A symref (see glossary) to the refs/heads/ namespace describing the currently active  
branch. It does not mean much if the repository is not associated with any working tree  
(i.e. a bare repository), but a valid git repository must have the HEAD file; some  
porcelains may use it to guess the designated "default" branch of the repository  
(usually master). It is legal if the named branch name does not (yet) exist.

So you're going to see HEAD as part of the branch list, even if "it does not mean much..."

Paul
  • 16,255
  • 3
  • 33
  • 25
  • This doesn't make sense. Repositories start out bare but the minute you push something to them, they are no longer bare and if you run "git branch" on them they will show a currently checked out branch. – geoidesic Aug 17 '14 at 13:36
  • @geoidesic A repository could be bare even if you have pushed to it. The following: `mkdir foobar; cd foobar; git init --bare; cd ..; git clone foobar foobar_clone; cd foobar_clone; touch file; git add file; git config --global user.email "you@example.com"; git config --global user.name "Your Name"; git commit -m "test"; git push origin master; cd ..; cd foobar; git config core.bare` outputs true. Also there is no working copy of the pushed file in the foobar repo upon those commands. – Anders Lindén Jun 19 '16 at 10:08
  • @geoidesic A repository could be bare even if you have pushed to it. The following: `mkdir foobar; cd foobar; git init --bare; cd ..; git clone foobar foobar_clone; cd foobar_clone; touch file; git add file; git config user.email "you@example.com"; git config user.name "Your Name"; git commit -m "test"; git push origin master; cd ..; cd foobar; git config core.bare` outputs true. Also there is no working copy of the pushed file in the foobar repo upon those commands. – Anders Lindén Jun 19 '16 at 10:10
  • @geoidesic A --bare git repo just means a repo with no working tree, i.e. a repo that only contains a .git-directory, but can not have any checked out files at all. Since it can't have any checked out files, it actually doesn't even have a .git directory, it just puts all the .git files directly in the main directory. Create one and you will see! – 00prometheus Jun 26 '20 at 10:19
7

If "origin" is a remote repository, then origin/HEAD identifies the default branch on that remote repository.

Example:

$ git remote show
origin
$ git remote show origin
* remote origin
  Fetch URL: git@github.com:walkerh/pipe-o-matic.git
  Push  URL: git@github.com:walkerh/pipe-o-matic.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (fast-forwardable)

Note the line that says "HEAD branch: master". This is where the remote repository lets clients know which branch to checkout by default.

Walker Hale IV
  • 3,252
  • 2
  • 21
  • 11
1

There's always a HEAD that points to the currently checked out branch on the remote repo (which may or may not be master). Even remote repositories have current branches. Usually it is master, and off the top of my head I can't think of any reason why one would want to change it, but it can be changed.

codelogic
  • 71,764
  • 9
  • 59
  • 54
  • 2
    github repos don't have checked out branches. I don't see why this would apply. – Dustin Dec 11 '08 at 04:37
  • Remote repositories should NOT have a working directory. Remote repositories should be --bare and can thus not have a currently checked out branch. – n4rzul Dec 01 '15 at 11:45
-16

My guess is that someone pushed a branch and called it HEAD:

git push origin HEAD
Dustin
  • 89,080
  • 21
  • 111
  • 133
  • Can I get some comments as to what's wrong with this? If you want an origin/HEAD on github, that's the only way I know to get it there. – Dustin Dec 11 '08 at 04:37
  • The remote HEAD is a symbolic ref (usually to refs/heads/master). You will replace the symbolic ref by the hash id of the commit of your current branch. – Daniel Fanjul May 11 '09 at 10:32
  • 5
    Shouldn't guesses be discussed in comments instead of being an imprecise answer? – Luciano Oct 25 '18 at 13:46