jcubic
jcubic

Reputation: 66478

How to checkout git branch that was created from the GitHub website?

So I've created a quick change on the GitHub repo, but it requires more work, adding unit tests, and running the build. So I have new branch created with web interface:

https://github.com/jcubic/prism/tree/patch-1

But when I use git pull, in the terminal, I have nothing was changed. When I use git branch -a I've got:

$ git branch -a
* master
  scheme-operators
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/upstream/gh-pages
  remotes/upstream/master

no branch patch-1. I have this in .git/config:

[remote "origin"]
        url = [email protected]:jcubic/prism.git
        fetch = +refs/heads/master:refs/remotes/origin/master

How I can update my local repo with stuff that is on GitHub?

EDIT:

It may be a bug on the GitHub side. It was reported and I'm waiting for a reply.

Upvotes: 0

Views: 2533

Answers (3)

torek
torek

Reputation: 487775

This:

[remote "origin"]
        url = [email protected]:jcubic/prism.git
        fetch = +refs/heads/master:refs/remotes/origin/master

is the problem. Note the fetch line here; this is the result of using git clone --single-branch or one of its several equivalents.

Having made a single-branch clone that you want to be a multi-branch clone, the recommended method is to use git remote to update the set of branches to fetch. I personally prefer to just run git config --edit and use my editor, but:

git remote set-branches origin "*"

will do the trick, and avoids some possible pitfalls that might occur with git config --edit.

Your real goal here is to make these three lines read:

[remote "origin"]
        url = [email protected]:jcubic/prism.git
        fetch = +refs/heads/*:refs/remotes/origin/*

Note the change to the third line: we now have our (local) Git (our Git software, running on this repository) call up their Git as usual, but this time, when their Git—their software on their repository—lists out all their branches, our Git says "yes! I'll take all of those!" With just master listed, our Git picks over their branches: Oh, hm, patch-1, that's not interesting. "feature", no, pass! "fix-23"? No way. "master": ah, that's the only one we care about: yes please!

When our Git says it doesn't want any of their branches except master, they only send us the pieces we need to make our origin/master—our memory of their master—and not any of the pieces we need to make our own origin/patch-1, for instance. So by explicitly rejecting their patch-1, you never get an origin/patch-1, and hence cannot create your own patch-1 from their patch-1.

Undoing the single-branch-ness fixes all of this, and now:

git fetch origin

gets, from them, all of their branches, turning them into all your remote-tracking names, origin/*.

About git fetch --all

hreikin's answer mentions git fetch --all (and git fetch --multiple; there are other additional variants). These are sometimes useful when you have more than one remote.

A remote is a name-and-URL set, and you do in fact have more than one remote:

$ git branch -a
* master
  scheme-operators
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/upstream/gh-pages
  remotes/upstream/master

This shows us that you have remotes named origin and upstream. These each represent different Git repositories to which you connect your Git repository.

Sometimes, you have your Git call up the Git over at origin, to see what branches and commits they have. These go into your repository under your origin/* names—currently, origin/master only, because you've told your Git that all other branches are too boring for words.

Other times, you have your Git call up the Git over at upstream, to see what branches and commits they have. These go into your repository under your upstream/* names.

With git fetch, you direct your Git to call up one other Git. Which one? Well, that depends: each branch, in your repository, is allowed to list one thing that Git calls an upstream. This name is a little bit unfortunate, since it's also the name of one of your remotes. But the upstream of your master branch is typically your origin/master: your remote-tracking name for the branch master on the Git you call origin.

The default, when you run git fetch, is to call up the Git that holds the branch that your current branch is using as its remote-tracking name. So if you're on your master, and its upstream is set to origin/master, your Git will run git fetch origin when you run git fetch without naming which Git to fetch from.

If you run git fetch upstream, though, your Git will fetch from upstream instead of origin. Or, you could create some other branch whose upstream is set to upstream/master or upstream/gh-pages:

git branch upmaster upstream/master
git checkout upmaster
git fetch

and now your Git would fetch from upstream (the remote named upstream), because the upstream of upmaster is upstream/master, which uses upstream as its remote. (Confused yet? If not, Git has still other confusing terms to use! 😀 Seriously, these historical accidents have made quite a mess here.)

Anyway, this particular thing—where git fetch fetches from one remote—works great when there's only one remote (usually called origin). But once you have two or more, it's nice to be able to fetch from all of them.

That's what the --all flag is for. It means fetch all remotes. It never means fetch all branches: the branches you get are per-remote, specified by that fetch = line.1 But in practice, it doesn't make a lot of sense to use git fetch --all, because there is another command:

git remote update

that means fetch all. The git remote command has a lot more tuning options, with the idea of "group" fetches from your most-commonly-used remotes for instance. These can all be done by git fetch but git remote is the command that's really aimed at this kind of fine detail.

The bottom line, as it were, is:

  • use git fetch to fetch from the remote for this branch;
  • use git remote update to fetch from all remotes, if you have more than one.

With these as general rules, and knowledge of how upstreams and fetch = lines work, you're now all set.


1Technically, you can have more than one line per remote. You can also override these lines using a refspec on the command line.

Upvotes: 2

hreikin
hreikin

Reputation: 30

You need to fetch the branches from the remote first.

  • To fetch all branches from the remote you are tracking locally you can run git fetch --all
  • To fetch from a specific remote, origin in this case, run git fetch origin
  • To fetch from multiple remotes, origin and upstream in this case, run git fetch --multiple origin upstream
  • Then to view all the branches run git branch -a
  • Then to checkout the branch run git checkout nameofnewbranch

The documentation for 'git fetch' is available here.

Upvotes: 0

dan1st
dan1st

Reputation: 16338

You need to use git fetch first.

This downloads all branches and their commit histories from GitHub (note that git pull also runs git fetch but also a git merge).

After running git fetch, you can see the remote branch with git branch -a.

Then, you can check it out using git checkout patch-1 or git checkout -b patch-1 remotes/origin/patch-1.

Upvotes: 0

Related Questions