Track all remote git branches as local branches

The answer given by Otto is good, but all the created branches will have "origin/" as the start of the name. If you just want the last part (after the last /) to be your resulting branch names, use this:

for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done

It also has the benefit of not giving you any warnings about ambiguous refs.


Using bash:

after git 1.9.1
for i in `git branch -a | grep remote | grep -v HEAD | grep -v master`; do git branch --track ${i#remotes/origin/} $i; done

credits: Val Blant, elias, and Hugo

before git 1.9.1

Note: the following code if used in later versions of git (>v1.9.1) causes

  1. (bug) All created branches to track master
  2. (annoyance) All created local branch names to be prefixed with origin/
for remote in `git branch -r `; do git branch --track $remote; done

Update the branches, assuming there are no changes on your local tracking branches:

for remote in `git branch -r `; do git checkout $remote ; git pull; done

Ignore the ambiguous refname warnings, git seems to prefer the local branch as it should.


Most of the answers here are over complicating the parsing of the output of git branch -r. You can use the following for loop to create the tracking branches against all the branches on the remote like so.

Example

Say I have these remote branches.

$ git branch -r
  origin/HEAD -> origin/master
  origin/development
  origin/integration
  origin/master
  origin/production
  origin/staging

Confirm that we're not tracking anything other than master already, locally:

$ git branch -l    # or using just git branch
* master

You can use this one liner to create the tracking branches:

$ for i in $(git branch -r | grep -vE "HEAD|master"); do 
    git branch --track ${i#*/} $i; done
Branch development set up to track remote branch development from origin.
Branch integration set up to track remote branch integration from origin.
Branch production set up to track remote branch production from origin.
Branch staging set up to track remote branch staging from origin.

Now confirm:

$ git branch
  development
  integration
* master
  production
  staging

To delete them:

$ git br -D production development integration staging 
Deleted branch production (was xxxxx).
Deleted branch development (was xxxxx).
Deleted branch integration (was xxxxx).
Deleted branch staging (was xxxxx).

If you use the -vv switch to git branch you can confirm:

$ git br -vv
  development xxxxx [origin/development] commit log msg ....
  integration xxxxx [origin/integration] commit log msg ....
* master      xxxxx [origin/master] commit log msg ....
  production  xxxxx [origin/production] commit log msg ....
  staging     xxxxx [origin/staging] commit log msg ....

Breakdown of for loop

The loop basically calls the command git branch -r, filtering out any HEAD or master branches in the output using grep -vE "HEAD|master". To get the names of just the branches minus the origin/ substring we use Bash's string manipulation ${var#stringtoremove}. This will remove the string, "stringtoremove" from the variable $var. In our case we're removing the string origin/ from the variable $i.

NOTE: Alternatively you can use git checkout --track ... to do this as well:

$ for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); do 
    git checkout --track $i; done

But I don't particularly care for this method, since it's switching you among the branches as it performs a checkout. When done it'll leave you on the last branch that it created.

References

  • 10.1. Manipulating Strings - Advanced Bash Scripting Guide
  • 3.5 Git Branching - Remote Branches

Update Q1 2020: Mohsen Abasi proposes in the comments, based on the 2014 slm's answer, the simpler alternative:

for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); 

And it uses $() instead of obsolete backticks.

As I mention in another old answer, using git for-each-ref is probably faster.
And I would use the new (Git 2.23+) git switch command, which replaces the confusing git checkout.

for i in $(git for-each-ref --format=%(refname:short) \
  --no-merged=origin/HEAD refs/remotes/origin); do \
    git switch --track $i; \
done

That way, no grep needed.


Old (2011) original answer:

Here is my one-liner I use (in a bash shell, tested with msysgit1.7.4):

For copy-paste:

remote=origin ; for brname in `git branch -r | grep $remote | grep -v master | grep -v HEAD | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream-to $remote/$brname $brname; done

For more readability:

remote=origin ; // put here the name of the remote you want
for brname in `
    git branch -r | grep $remote | grep -v master | grep -v HEAD 
    | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'
`; do 
    git branch --set-upstream-to $remote/$brname $brname; 
done
  • it will only select upstream branches from the remote you specify in the remote variable (it can be 'origin' or whatever name you have set for one of the remotes of your current Git repo).
  • it will extract the name of the branch: origin/a/Branch/Name => a/Branch/Name through the awk expression.
  • it will set the upstream branch through --set-upstream-to (or -u), not --track:
    The advantage is that, if the branch already exists, it won't fail and it won't change that branch origin, it will only configure the branch.xxx.(remote|merge) setting.

    branch.aBranchName.remote=origin
    branch.aBranchName.merge=refs/heads/a/Branch/Name
    

That command will create local branches for all remote upstream branches, and set their remote and merge setting to that remote branch.


You could script that easily enough, but I don't know when it'd be valuable. Those branches would pretty quickly fall behind, and you'd have to update them all the time.

The remote branches are automatically going to be kept up to date, so it's easiest just to create the local branch at the point where you actually want to work on it.