Reputation: 2421
Tracking a single remote branch as a local branch is straightforward enough.
git checkout --track -b ${branch_name} origin/${branch_name}
Pushing all local branches up to the remote, creating new remote branches as needed is also easy.
git push --all origin
I want to do the reverse. If I have X number of remote branches at a single source:
git branch -r
Output:
branch1
branch2
branch3
.
.
.
Can I create local tracking branches for all those remote branches without needed to manually create each one? Say something like:
git checkout --track -b --all origin
I've googled and read the manuals, but have come up bunk thus far.
Upvotes: 216
Views: 103176
Reputation: 551
Without any scripting (in an empty directory):
$ git clone --bare repo_url .git
$ git config core.bare false
$ git checkout
After that, all remote branches will be seen as local.
Upvotes: 17
Reputation: 401
In case you already have some branches checked out and want to
you can use the following Bash- and Z shell-compatible script:
git branch -r | while read b; do if git branch | grep -q " ${b##*/}$"; then git branch --set-upstream ${b##*/} $b; else git branch --track ${b##*/} $b; fi; done
Upvotes: 0
Reputation: 3609
Use:
#!/usr/bin/env bash
# Go from a shallow clone of the main branch
# to a deep clone of all branches
# Excluding mounted worktrees is required to avoid errors like:
# fatal: refusing to fetch into branch 'refs/heads/master' checked out at '/tmp/repo'
remote=${1:-origin}
git fetch $remote --depth=99999999 $(
git ls-remote --heads $remote |
cut -d/ -f3- |
grep -v -x -E $(
git worktree list --porcelain |
grep ^branch | cut -c19- | tr $'\n' '|'
) |
sed 's/.*/&:&/'
)
This will expand to something like:
git fetch origin --depth=99999999 \
branch1:branch1 \
branch2:branch2 \
branch2:branch3
Upvotes: 0
Reputation: 162
VonC's solution can be simplified even further by changing the sed (I lack the rep points to comment directly on his post):
for branch in $(git branch -r | sed 's,[^/]*/,,g'); do git switch $branch; done
By replacing everything that isn't a slash up to the final slash, the remaining branch name is suitable for local use; repeatedly switching to the same branch isn't an error (it may be inefficient, but it may be more efficient than having a grep in the pipe :->).
The switch command is smart enough to track each remote branch as necessary.
Upvotes: 2
Reputation: 3453
From Git 2.23 onwards:
for branch in `git branch -r | grep origin/`; do git switch -t -C ${branch#origin/} $branch; git pull; done
The -C
flag for git switch
creates or resets if it already exists.
Upvotes: 3
Reputation: 11
Using Bash, if you want to checkout all branches:
for remote in `git branch -r`; do git checkout $(echo $remote | cut -d'/' -f 2); done
It’s important to note that when you do a fetch that brings down new remote-tracking branches, you don’t automatically have local, editable copies of them.
Upvotes: 1
Reputation: 4149
Here is my solution of a Bash command referred to by @tjmcewan:
for remote in `git branch -r | grep -v /HEAD `; do git branch --track ${remote/"origin/"/""}; done
My goal is to solve the problem that all the created branches will have "origin/" as the start of the name, because I tested that $remote variables are still include "origin/":
for remote in `git branch -r | grep -v /HEAD`; do echo $remote ; done
Upvotes: 3
Reputation: 9
Use:
for rembranch in `git remote update 2>&1 > /dev/null ; git branch -r|egrep -wv "HEAD|master"`
do
git checkout --track -b `echo $rembranch|awk -F\/ '{print $2}'` $rembranch;
done
Explanation:
Line 1: 'git branch -r' (followed by 'git remote update' to update the info on changes to remote) lists all remote branches; 'egrep -vw' is used to knock entries having HEAD and master in the result.
Line 3: Track the named remote branch while checking it out locally. A simple AWK is used to avoid 'origin/' being the suffix for local branches.
Upvotes: 0
Reputation: 2528
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.
Upvotes: 211
Reputation: 19361
Using Bash:
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
Note: the following code if used in later versions of Git (>v1.9.1) causes
- (bug) All created branches to track master
- (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.
Upvotes: 150
Reputation: 1329932
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/^[ ]\+//'); do git switch --track $i; done
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.
Upvotes: 26
Reputation: 2192
If you want to use powershell and your remote is called origin. Then this works.
git fetch
git branch -r | %{$_ -replace " origin/"} | %{git branch --track $_ "origin/$_"}
Upvotes: 8
Reputation: 16446
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.
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 ....
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.
Upvotes: 28
Reputation: 29394
To do the same as tjmcewan's answer but on Windows, call this from a batch file:
for /f "delims=" %%r in ('git branch -r ^| grep -v master') do git checkout --track %%r
Or this from the command line:
for /f "delims=" %r in ('git branch -r ^| grep -v master') do git checkout --track %r
Upvotes: 3
Reputation: 1772
for i in `git branch -a | grep remote`; do git branch --track ${i#remotes/origin/} $i; done
Upvotes: 10
Reputation: 5693
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do git branch --track ${branch##*/} $branch; done
Use this and you will not have such warning as: refname 'origin/dev' is ambiguous
Upvotes: 3
Reputation: 91050
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.
Upvotes: 15