1

I am trying to understand my following situation:

There is a project in Github that me and other people are using. I believe it has several branches besides master (in particular "develop")

So I cloned the project to my computer with git clone <url> and I got the project. I have been told that I should work with the develop branch not with the master branch

So I type git branch to see what branches are there and I got

$ git branch
* master

What? where is the develop branch?

Nevertheless I do git checkout develop and behold! I am now in the develop branch! I do git branch again and I could see

$ git checkout develop
Branch develop set up to track remote branch develop from origin.
Switched to a new branch 'develop'
$ git branch
* develop
  master

what dark magic is happening here?? It says that develop was set to track the develop from origin! So before that develop was hidden? unreachable?

After doing git log --oneline --decorate I could see the origin/develop branch but what just happened here??

RomainValeri
  • 14,254
  • 2
  • 22
  • 39
KansaiRobot
  • 3,881
  • 3
  • 33
  • 74
  • 1
    `git clone` creates remote-tracking branches for each branch repository. – Maroun Aug 13 '18 at 07:26
  • Yes, and if you want just to clone one single branch, have a look at [this](https://stackoverflow.com/questions/1778088/how-to-clone-a-single-branch-in-git) SO answer. – YesThatIsMyName Aug 13 '18 at 07:29
  • @Maroun so I have to use `git branch -a` to see everything and checkout to the one I want to work with? – KansaiRobot Aug 13 '18 at 07:31
  • 1
    @KansaiRobot Yes. – Maroun Aug 13 '18 at 07:31
  • 1
    @KansaiRobot When you do `git branch -a`, remotes will be prefixed with `remotes/origin` or maybe `remotes/` if your remote happens not be named `origin` (it's only a convention after all, even if very commonly used). Don't `git checkout remotes/origin/myBranch` but rather `git checkout myBranch` if you want to create a local version tracking the remote one. – RomainValeri Aug 13 '18 at 07:36
  • Possible duplicate of [How to clone all remote branches in Git?](https://stackoverflow.com/questions/67699/how-to-clone-all-remote-branches-in-git) – phd Aug 14 '18 at 14:09
  • @phd Nope, I am not asking that – KansaiRobot Aug 15 '18 at 00:30

2 Answers2

6

Yes, you have only one branch after git clone

In fact, just before git clone finishes, you have no branches.

But "having a branch" does not mean that much

Git uses branch names to remember specific commits. Each name remembers one, and only one, commit. Each commit is uniquely identified by its hash ID: a big ugly number like b7bd9486b055c3f967a870311e704e3bb0654e4f.

It's the commits themselves that remember previous commits (by their big ugly hash IDs). Git calls this the parent commit of each commit. This means that a name like master is needed only to remember the last commit of any given branch. Git calls this final commit the tip of the branch.

It also means that we can use a different, not-quite-a-branch, name to remember some other Git's branches!

Enter the remote-tracking branch

Making a clone involves, internally, running git fetch. It's git fetch that copies the commits from some other Git, and git fetch also copies their names. Their names are in fact branch names: these remember their branch tips, like master and develop. But they're not your branch tip commits—not yet! Your Git renames these, to origin/master and origin/develop. Your Git's remote-tracking names, with the origin prefixes, remember their names and their tip commits.

Running git fetch updates your remote-tracking names, so that you know what their new branch tip commits are. Of course, it also first gets any commits they have, that you don't.

The dark magic

[develop suddenly appears:] what dark magic is happening here?

When you run git checkout name, Git starts by searching through your list of branch names for name. If it exists, Git tries to check out the specific commit that is the tip of your branch name, and make that your current branch. So far so good—but what if the name doesn't exist yet?

In this case, instead of just failing, git checkout searches through your remote-tracking names, like origin/master and origin/develop. If there's exactly one that resembles the name you asked for, your Git now creates your own branch name, setting it to remember, as your branch tip commit, the same hash ID that your Git is remembering as their tip, using that remote-tracking name.

So now you have a develop and now Git can check it out!

In fact, this was the very last step of git clone: it's how you got your master in the first place. After copying commits from origin, and changing their names to origin/*, your Git ran git checkout master. Your master did not exist yet, so your Git created it from your origin/master that your Git created from their master. (Whew! It seems like the long way around, and it is, but it does all make sense eventually!)

torek
  • 330,127
  • 43
  • 437
  • 552
  • @KansaiRobot, please read [this](https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches) and [this](https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows) to get the full grasp on the topic. I'd say reading the whole book it recommended. But especially importand is understanding that _all Git repositories are completely **free-standing** and independent,_ and all "linkage" between the branches in any repository with the branches in any other repository is completely a policy thing. – kostix Aug 13 '18 at 08:13
3

Short answer

When you clone (then later when you fetch), your local version of the repo gets the updated definitions of remote branches but local counterparts are not created automatically. If you just checkout a (yet non existing locally) branch whose name matches one of the remote ones, git assumes for you that you need to track the remote version of the same.

Try git branch -a to see everything.

For more, see torek's very complete answer to unpack the details behind it.

RomainValeri
  • 14,254
  • 2
  • 22
  • 39