[git] Git branching: master vs. origin/master vs. remotes/origin/master

I think I'm on the right track to understand the basic concepts of git.

I've already set up and cloned a remote repository. I also created a server side empty repository, and linked my local repository to it.

My problem is that I don't understand the difference between:

  • origin/master vs. remotes/origin/master

As far as I have understood, master is a local branch, and remotes/origin/master is a remote one.

But what exactly is origin/master?

This question is related to git git-remote

The answer is


I think this git slash notation is probably best understood by looking inside your .git folder.


For example, here is a somewhat abbreviated tree of my .git for the LibreOffice source base.

In linux sudo apt-get install tree is useful to view this.
In Windows I think the tree command might still work.

Scroll down and take a look at refs (aka 'references') near the bottom:

$ tree  
.  
+-- branches  
+-- config  
+-- description  
+-- FETCH_HEAD  
+-- gitk.cache  
+-- HEAD  
+-- hooks  
¦   +-- applypatch-msg.sample  
    ...
+-- index  
+-- info  
¦   +-- exclude  
+-- logs  
¦   +-- HEAD  
¦   +-- refs  
¦       +-- heads  
¦       ¦   +-- master  
¦       ¦   +-- remotes  
¦       ¦       +-- origin  
¦       +-- remotes  
¦           +-- origin  
¦               +-- distro  
¦               ¦   +-- cib  
¦               ¦   ¦   +-- libreoffice-6-0  
¦               ¦   +-- collabora  
¦               ¦   ¦   +-- cp-6.0  
¦               ¦   +-- lhm  
¦               ¦       +-- libreoffice-5-2+backports  
¦               +-- HEAD  
¦               +-- libreoffice-6-2  
¦               +-- master  
¦               +-- private  
¦                   +-- mst  
¦                       +-- sw_redlinehide_4a  
+-- objects  
¦   +-- info  
¦   +-- pack  
¦       +-- pack-b80087dc57e2b3315f449ca0f1aaa91987bf0c5e.idx  
¦       +-- pack-b80087dc57e2b3315f449ca0f1aaa91987bf0c5e.pack  
¦       +-- pack-eb4e6808029e712d8d9c2671accbbd98aaeb9a04.idx  
¦       +-- pack-eb4e6808029e712d8d9c2671accbbd98aaeb9a04.pack  
+-- ORIG_HEAD  
+-- packed-refs  
+-- refs  
    +-- heads  
    ¦   +-- master  
    ¦   +-- remotes  
    ¦       +-- origin  
    +-- remotes  
    ¦   +-- origin  
    ¦       +-- distro  
    ¦       ¦   +-- cib  
    ¦       ¦   ¦   +-- libreoffice-6-0  
    ¦       ¦   +-- collabora  
    ¦       ¦   ¦   +-- cp-6.0  
    ¦       ¦   +-- lhm  
    ¦       ¦       +-- libreoffice-5-2+backports  
    ¦       +-- HEAD  
    ¦       +-- libreoffice-6-2  
    ¦       +-- master  
    ¦       +-- private  
    ¦           +-- mst  
    ¦               +-- sw_redlinehide_4a  
    +-- tags  
        +-- libreoffice-6-2-branch-point  

32 directories, 45 files

It might have been less confusing if it was laid out like this, but it wasn't:

repositories (i.e. independent trees)
+--local
¦  +--master
¦
+--origin1
¦  +--master
+--origin2
   +--master

We have three basic types of references: heads, remotes, and tags.

  • .git/refs/heads holds our local master.

  • .git/refs/remotes can hold a number of remotes, although at the moment we only have origin in it.

  • .git/refs/tags (is discussed elsewhere).

origin thus, is our one and only remote. It holds origin/master.


We find that we have 2 HEADS (pointers to current branches), one local, and one remote:

$ cat .git/HEAD                        #         local:  HEAD -> master
ref: refs/heads/master

$ cat .git/refs/remotes/origin/HEAD    # remote origin:  HEAD -> master
ref: refs/remotes/origin/master

If you list your branches:

$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/aoo/aw080
  remotes/origin/aoo/trunk
  remotes/origin/distro/capgemini/cg-4.1
  remotes/origin/distro/cib/libreoffice-5-0
  remotes/origin/distro/cib/libreoffice-5-1
  remotes/origin/distro/cib/libreoffice-5-2
  ...
  • The first branch listed (master) is the only one which is not a remote. So in this case we have one local branch. This is where we'll start our own work from, for our own new branches and subsequent commits.

Next, you may have many remote tracking branches, and we do here. You know these are remote tracking branches because they are prefixed with 'remotes/'. The ones shown here are for the remote named origin.

  • So the second line is origin's current branch pointer. Remotes/origin: HEAD --points to--> master. This shows that in the remote repository, the current branch is their branch named master, (not to be confused with our local branch named master).

  • The remaining branches aren't found in your .git/refs/ tree, but rather you'll find them in .git/packed-refs.

When we git fetch we download changes from the remote repository, into our remote tracking repository.

When we git merge we merge the changes in this local, remote tracking repository into our working local branch or branches, in this case into our master branch.

(When we git pull we do both of these two steps in one operation.)


It's also interesting to note these local and remote UUIDs for master currently point to the same node (aka 'commit'):

$ cat refs/heads/master                   # local         master
1ca409292272632f443733450313de5a82c54a9c

$ cat refs/remotes/origin/master          # remote origin master
1ca409292272632f443733450313de5a82c54a9c

So our local master points to the same place as the remote's origin master:

[local] master = [remote] origin master

Finally, I think it's also useful to take a look at .git/packed-refs

$ cat packed-refs 
# pack-refs with: peeled fully-peeled 
3c1d4742e649fe9c8aed8c2817fe3e1f3364f298 refs/remotes/origin/aoo/aw080
e87c8b7922e9a73e0abb7f9a7a47c9ac3374a826 refs/remotes/origin/aoo/trunk
b70fdffb041c12f124dcc0822b61bf3450e53137 refs/remotes/origin/distro/capgemini/cg-4.1
5dbc3f1754809b9489faaf380b1a4bdbcfbb6205 refs/remotes/origin/distro/cib/libreoffice-5-0
cfdbc96ca47d68d6785fd21829a8d61f49d6e591 refs/remotes/origin/distro/cib/libreoffice-5-1
5189c8c47461ef09739086e55512fc6a10245273 refs/remotes/origin/distro/cib/libreoffice-5-2
3bee5917569ca8e6ee3b086458f5b1a917b88ca1 refs/remotes/origin/distro/cib/libreoffice-5-3
92fbe703f9ca480d3a2b8610d87e991c729edf77 refs/remotes/origin/distro/cib/libreoffice-5-4
05c0a5df66cc69d75280f05b804cf82f3387d42b refs/remotes/origin/distro/cib/libreoffice-6-0
7fe193e759b24b90852e6e327115b77114d7b119 refs/remotes/origin/distro/cib/libreoffice-6-1
8187f7aa413e7ef7b377eea2b057d336bf256867 refs/remotes/origin/distro/collabora/cd-5.3
7a6b608591e21ef61dc05cff9fc58da531035755 refs/remotes/origin/distro/collabora/cd-5.3-3.1
....

No doubt this leaves more questions than answers, but I think it can start to help you answer your own questions about what's what.


One clarification (and a point that confused me):

"remotes/origin/HEAD is the default branch" is not really correct.

remotes/origin/master was the default branch in the remote repository (last time you checked). HEAD is not a branch, it just points to a branch.

Think of HEAD as your working area. When you think of it this way then 'git checkout branchname' makes sense with respect to changing your working area files to be that of a particular branch. You "checkout" branch files into your working area. HEAD for all practical purposes is what is visible to you in your working area.


Technically there aren't actually any "remote" things at all1 in your Git repo, there are just local names that should correspond to the names on another, different repo. The ones named origin/whatever will initially match up with those on the repo you cloned-from:

git clone ssh://some.where.out.there/some/path/to/repo # or git://some.where...

makes a local copy of the other repo. Along the way it notes all the branches that were there, and the commits those refer-to, and sticks those into your local repo under the names refs/remotes/origin/.

Depending on how long you go before you git fetch or equivalent to update "my copy of what's some.where.out.there", they may change their branches around, create new ones, and delete some. When you do your git fetch (or git pull which is really fetch plus merge), your repo will make copies of their new work and change all the refs/remotes/origin/<name> entries as needed. It's that moment of fetching that makes everything match up (well, that, and the initial clone, and some cases of pushing too—basically whenever Git gets a chance to check—but see caveat below).

Git normally has you refer to your own refs/heads/<name> as just <name>, and the remote ones as origin/<name>, and it all just works because it's obvious which one is which. It's sometimes possible to create your own branch names that make it not obvious, but don't worry about that until it happens. :-) Just give Git the shortest name that makes it obvious, and it will go from there: origin/master is "where master was over there last time I checked", and master is "where master is over here based on what I have been doing". Run git fetch to update Git on "where master is over there" as needed.


Caveat: in versions of Git older than 1.8.4, git fetch has some modes that don't update "where master is over there" (more precisely, modes that don't update any remote-tracking branches). Running git fetch origin, or git fetch --all, or even just git fetch, does update. Running git fetch origin master doesn't. Unfortunately, this "doesn't update" mode is triggered by ordinary git pull. (This is mainly just a minor annoyance and is fixed in Git 1.8.4 and later.)


1Well, there is one thing that is called a "remote". But that's also local! The name origin is the thing Git calls "a remote". It's basically just a short name for the URL you used when you did the clone. It's also where the origin in origin/master comes from. The name origin/master is called a remote-tracking branch, which sometimes gets shortened to "remote branch", especially in older or more informal documentation.


I would try to make @ErichBSchulz's answer simpler for beginners:

  • origin/master is the state of master branch on remote repository
  • master is the state of master branch on local repository

Short answer for dummies like me (stolen from Torek):

  • origin/master is "where master was over there last time I checked"
  • master is "where master is over here based on what I have been doing"

  1. origin - This is a custom and most common name to point to remote.

$ git remote add origin https://github.com/git/git.git --- You will run this command to link your github project to origin. Here origin is user-defined. You can rename it by $ git remote rename old-name new-name


  1. master - The default branch name in Git is master. For both remote and local computer.

  1. origin/master - This is just a pointer to refer master branch in remote repo. Remember i said origin points to remote.

$ git fetch origin - Downloads objects and refs from remote repository to your local computer [origin/master]. That means it will not affect your local master branch unless you merge them using $ git merge origin/master. Remember to checkout the correct branch where you need to merge before run this command

Note: Fetched content is represented as a remote branch. Fetch gives you a chance to review changes before integrating them into your copy of the project. To show changes between yours and remote $git diff master..origin/master