I can say this:
git push --all origin
and it will push all branches to origin. But if I do this:
git pull --all origin
then it doesn't pull all the branches from origin, it just returns an error:
fatal: fetch --all does not take a repository argument
Ok, I do this:
git pull --all
buy yet it says:
You asked to pull from the remote '--all', but did not specify
a branch. Because this is not the default configured remote
for your current branch, you must specify a branch on the command line.
So how do I pull all the branches from origin (like I push all branches to origin by git push --all origin
)?
VonC's answer contains all items you need to make various setups work, but could use a bit of background explanation for those somewhat new to git.
In what I think is a very unfortunate bit of naming, git has fetch
, push
, and pull
. It sounds like pull
is the opposite-direction equivalent of push
, but it's not! The closest thing push
has to an opposite is actually fetch
(and even then they're not entirely symmetric).
To properly understand all this, you need to know that in git, branch names are merely labels for specific commits, with one very special property. A "regular" or "local" branch name—usually just called "a branch"—like master
has the special property that, when you check it out by branch name and then make new commits in your repository, that branch name automatically moves forward to include your new commits. (And each new commit points back to its "parent" older commit—or, for merges, to all its parents.)
Git also provides "remote branches", which (in git tradition) have a somewhat misleading name since they also live in your repository, not in some other "remote" repository. These are prefixed with the name of the remote, e.g., origin
, so you have origin/master
as a "remote branch". Again, these are just labels for commits. Unlilke your local branches, they don't move when you make commits—but they do move. They move when you use git fetch
.
When you run git fetch
, your git contacts some remote (origin
) and asks it what branches1 it has, and what those labels point to. You can see this by running git ls-remote
:
$ git ls-remote
From ssh://[redacted]
d1574b852963482d4b482992ad6343691082412f HEAD
222c4dd303570d096f0346c3cd1dff6ea2c84f83 refs/heads/branch
d1574b852963482d4b482992ad6343691082412f refs/heads/master
d41117433d7b4431a188c0eddec878646bf399c3 refs/tags/tag-foo
A normal fetch
brings over all the branches, writing them into your repository under different names. In this case, master
becomes origin/master
and branch
becomes origin/branch
.2
To bring over a branch-label, it also brings over the commit itself (such as 222c4dd...
above), plus any other underlying objects needed to make the commit complete. (This includes any development history that they have, that you don't already have.) Then the new, remote-adjusted branch name (origin/branch
) is set to point directly to that commit (222c4dd...
).
Thus, as already noted, git fetch
brings over all branches, just as git push --all
pushes all branches. What fetch
does not do is merge any of those updates into your own local branches. This is also where fetch
and push
stop being mirror-images of each other: when you push
a branch to a remote, there is no automatic renaming.3
Again, when we bring over their master
, it becomes origin/master
. None of our branches are named origin/whatever
, so this can't possibly break our branches. But when we push our master
to them, we just tell them to set it up as their master
. We don't say: "push our master
to your alexander/master
".4 This is why, before we push, we usually have to either merge or rebase our master
with theirs, so that when we tell them "hey, set your master
to commit af7c315
", we make sure that this new commit-ID incorporates all the history they have, so that they don't lose any.
This is where git pull
comes in. To update their master
, we need to first bring over their master
, with git fetch
, which will rename it origin/master
in our local copy. Then, once we're in sync with them, we merge-or-rebase our master
and our origin/master
(which is now in sync with their master
). Finally, when that's done and is good, we can push our new master
—it's now based on / merged with our origin/master
that matches their master
—to their master
. As long as all this happens fast enough, this all works. (If it's not fast enough—if someone else beats us to the push
—then we have to fetch again, merge-or-rebase again, and try the push
again, repeating until we win the race against everyone else also trying to push
.)
The git pull
script simply automates the fetch-and-merge/rebase part. But it does this with only one branch: whatever branch we have checked out right now. This is because, in git, the merge
and rebase
commands only change one branch: merge
merges into the current branch, and rebase
generally rebases the current branch. (If you tell git rebase
to rebase some other branch, it does that by first checking it out.)
If you want to merge-or-rebase multiple branches, you have to check each one out, one at a time. (It's slightly easier with rebase
since git rebase origin/master master
starts by doing git checkout master
—so it's built in to the command—but you're still doing a git checkout
.) Fortunately git fetch origin
will update all the remote-branches at once, so you need only one git fetch
.
Git generally assumes that unless you plan to change something in a branch, or freeze it at a particular commit, you don't check out your own version of it. That is, you don't do:
$ git checkout --track feature origin/feature
unless you plan to do something with it. So unless you're already on branch feature
, there's no call to rebase-or-merge it.
Because git clone
does an initial checkout, usually of master
, while people often work on feature branches instead, it's pretty common to wind up with one branch you'll work on (feature
) and one local branch you don't need (master
). But there's nothing wrong with just leaving that branch to get further and further behind origin/master
until you do need it; or you can even just delete it, once you've done a git checkout
of some other branch:
$ git checkout branch # newer gits do --track automatically
Branch branch set up to track remote branch branch from origin.
Switched to a new branch 'branch'
$ git branch -d master
warning: deleting branch 'master' that has been merged to
'refs/remotes/origin/master', but not yet merged to HEAD.
Deleted branch master (was d1574b8).
$
(the warning is annoying but harmless).
1The fetch
can also see tags and other refs, and you can instruct it to bring more stuff over. The example above shows one tag, plus HEAD
. Adding --tags
, or changing the fetch =
line, allows you to bring the tags over. The HEAD
reference is extra-special, and there's a long-standing subtle bug in the way git treats HEAD
for clone operations, which is usually not important and requires a change in the protocols to fix, so no one has fixed it.
2More precisely, refs/heads/*
maps to refs/remotes/origin/*
with the *
part being copied across. So if the remote has a refs/heads/this/that
, you get refs/remotes/origin/this/that
. This is what the fetch =
line under the remote
definition in your .git/config
file is about: it tells fetch
how to re-map remote references. This is also why I say a "normal" fetch: you can configure it, or run it with options, to make it act differently.
People new to git might wonder why it does this renaming. Well, suppose you start by grabbing their master
and making a new local master
branch so that you can change things. Then you change some things, and use git add
and git commit
to create at least one new commit. Meanwhile they (whoever "they" are) have also changed things and made new commits. You want to see what they did, so you git fetch
their new stuff. If that overwrote your master
, what would happen to your work? Fortunately git brings over their new stuff under a different name: origin/master
. Your master
remains unchanged, tracking your new commits.
3At least, not by default. As with most things git, you can change this behavior, with command line flags and configuration entries.
4Actually, as already noted in footnote 3, we can do exactly that, and in some setups, you might even want to. But that's not generally how people use git with sharing repositories.
git pull
with first git fetch
everything, meaning the origin
namespace will include all (remote tracking) branches from origin
(see fetch all branches).
But it will merge only origin/currentBranch
to currentBranch
.
It won't create the other branches.
If it were to creates all the branches from origin
, your git branch would be "polluted" by the potentially many branches of the upstream repo.
Generally, you only want as local branches the one you will be working on.
If you want to track all branches from remote, you can refer to this one-liner from the question "Track all remote git branches as local branches".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With