How do I clone all remote branches?

Viewed 1587249

My master and development branches are tracked remotely on GitHub. How do I clone both these branches?

46 Answers

First, clone a remote Git repository and cd into it:

$ git clone git://example.com/myproject
$ cd myproject

Next, look at the local branches in your repository:

$ git branch
* master

But there are other branches hiding in your repository! See these using the -a flag:

$ git branch -a
* master
  remotes/origin/HEAD
  remotes/origin/master
  remotes/origin/v1.0-stable
  remotes/origin/experimental

To take a quick peek at an upstream branch, check it out directly:

$ git checkout origin/experimental

To work on that branch, create a local tracking branch, which is done automatically by:

$ git checkout experimental

Branch experimental set up to track remote branch experimental from origin.
Switched to a new branch 'experimental'

Here, "new branch" simply means that the branch is taken from the index and created locally for you. As the previous line tells you, the branch is being set up to track the remote branch, which usually means the origin/branch_name branch.

Your local branches should now show:

$ git branch
* experimental
  master

You can track more than one remote repository using git remote:

$ git remote add win32 git://example.com/users/joe/myproject-win32-port
$ git branch -a
* master
  remotes/origin/HEAD
  remotes/origin/master
  remotes/origin/v1.0-stable
  remotes/origin/experimental
  remotes/win32/master
  remotes/win32/new-widgets

At this point, things are getting pretty crazy, so run gitk to see what's going on:

$ gitk --all &

If you have many remote branches that you want to fetch at once, do:

git pull --all

Now you can checkout any branch as you need to, without hitting the remote repository.


Note: This will not create working copies of any non-checked out branches, which is what the question was asking. For that, see

This Bash script helped me out:

#!/bin/bash
for branch in $(git branch --all | grep '^\s*remotes' | egrep --invert-match '(:?HEAD|master)$'); do
    git branch --track "${branch##*/}" "$branch"
done

It will create tracking branches for all remote branches, except master (which you probably got from the original clone command). I think you might still need to do a

git fetch --all
git pull --all

to be sure.

One liner: git branch -a | grep -v HEAD | perl -ne 'chomp($_); s|^\*?\s*||; if (m|(.+)/(.+)| && not $d{$2}) {print qq(git branch --track $2 $1/$2\n)} else {$d{$_}=1}' | csh -xfs
As usual: test in your setup before copying rm -rf universe as we know it

Credits for one-liner go to user cfi

Regarding,

git checkout -b experimental origin/experimental

using

git checkout -t origin/experimental

or the more verbose, but easier to remember

git checkout --track origin/experimental

might be better, in terms of tracking a remote repository.

The fetch that you are doing should get all the remote branches, but it won't create local branches for them. If you use gitk, you should see the remote branches described as "remotes/origin/dev" or something similar.

To create a local branch based on a remote branch, do something like:

git checkout -b dev refs/remotes/origin/dev

Which should return something like:

Branch dev set up to track remote branch refs/remotes/origin/dev. Switched to a new branch "dev"

Now, when you are on the dev branch, "git pull" will update your local dev to the same point as the remote dev branch. Note that it will fetch all branches, but only pull the one you are on to the top of the tree.

When you do "git clone git://location", all branches and tags are fetched.

In order to work on top of a specific remote branch, assuming it's the origin remote:

git checkout -b branch origin/branchname

A git clone is supposed to copy the entire repository. Try cloning it, and then run git branch -a. It should list all the branches. If then you want to switch to branch "foo" instead of "master", use git checkout foo.

Self-Contained Repository

If you’re looking for a self-contained clone or backup that includes all remote branches and commit logs, use:

git clone http://user@repo.url
git pull --all

The accepted answer of git branch -a only shows the remote branches. If you attempt to checkout the branches you'll be unable to unless you still have network access to the origin server.

Credit: Gabe Kopley's for suggesting using git pull --all.

Note:
Of course, if you no longer have network access to the remote/origin server, remote/origin branches will not have any updates reflected in your repository clone. Their revisions will reflect commits from the date and time you performed the two repository cloning commands above.


Checkout a *local* branch in the usual way with `git checkout remote/origin/` Use `git branch -a` to reveal the remote branches saved within your `clone` repository.

To checkout ALL your clone branches to local branches with one command, use one of the bash commands below:

$ for i in $(git branch -a |grep 'remotes' | awk -F/ '{print $3}' \ 
| grep -v 'HEAD ->');do git checkout -b $i --track origin/$i; done

OR

If your repo has nested branches then this command will take that into account also:

for i in $(git branch -a |grep 'remotes' |grep -v 'HEAD ->');do \
basename ${i##\./} | xargs -I {} git checkout -b {} --track origin/{}; done

The above commands will checkout a local branch into your local git repository, named the same as the remote/origin/<branchname> and set it to --track changes from the remote branch on the remote/origin server should you regain network access to your origin repo server once more and perform a git pull command in the usual way.

Use my tool git_remote_branch (grb). You need Ruby installed on your machine). It's built specifically to make remote branch manipulations dead easy.

Each time it does an operation on your behalf, it prints it in red at the console. Over time, they finally stick into your brain :-)

If you don't want grb to run commands on your behalf, just use the 'explain' feature. The commands will be printed to your console instead of executed for you.

Finally, all commands have aliases, to make memorization easier.

Note that this is alpha software ;-)

Here's the help when you run grb help:

git_remote_branch version 0.2.6

  Usage:

  grb create branch_name [origin_server]

  grb publish branch_name [origin_server]

  grb rename branch_name [origin_server]

  grb delete branch_name [origin_server]

  grb track branch_name [origin_server]



  Notes:
  - If origin_server is not specified, the name 'origin' is assumed
    (git's default)
  - The rename functionality renames the current branch

  The explain meta-command: you can also prepend any command with the
keyword 'explain'. Instead of executing the command, git_remote_branch
will simply output the list of commands you need to run to accomplish
that goal.

  Example:
    grb explain create
    grb explain create my_branch github

  All commands also have aliases:
  create: create, new
  delete: delete, destroy, kill, remove, rm
  publish: publish, remotize
  rename: rename, rn, mv, move
  track: track, follow, grab, fetch

git clone --mirror on the original repo works well for this.

git clone --mirror /path/to/original.git
git remote set-url origin /path/to/new-repo.git
git push -u origin

Here's an answer that uses awk. This method should suffice if used on a new repo.

git branch -r | awk -F/ '{ system("git checkout " $NF) }'

Existing branches will simply be checked out, or declared as already in it, but filters can be added to avoid the conflicts.

It can also be modified so it calls an explicit git checkout -b <branch> -t <remote>/<branch> command.

This answer follows Nikos C.'s idea.


Alternatively we can specify the remote branch instead. This is based on murphytalk's answer.

git branch -r | awk '{ system("git checkout -t " $NF) }'

It throws fatal error messages on conflicts but I see them harmless.


Both commands can be aliased.

Using nobody's answer as reference, we can have the following commands to create the aliases:

git config --global alias.clone-branches '! git branch -r | awk -F/ "{ system(\"git checkout \" \$NF) }"'
git config --global alias.clone-branches '! git branch -r | awk "{ system(\"git checkout -t \" \$NF) }"'

Personally I'd use track-all or track-all-branches.

I'm cloning a repository from the Udemy course Elegant Automation Frameworks with Python and Pytest, so that I can later go over it OFFLINE. I tried downloading the zip, but this only comes for the current branch, so here are my 2 cents.

I'm working on Windows and, obviously, I resorted to the Ubuntu shell from the Windows Subsystem for Linux. Immediately after cloning, here's my branches:

$ git clone https://github.com/BrandonBlair/elegantframeworks.git

$ git branch -a

* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/config_recipe
  remotes/origin/functionaltests
  remotes/origin/master
  remotes/origin/parallel
  remotes/origin/parametrize
  remotes/origin/parametrize_data_excel
  remotes/origin/unittesting
  remotes/origin/unittesting1

Then — and after hitting a few git checkout brick walls —, what finally worked for me was:

$ for b in `git branch -a | cut -c18- | cut -d\  -f1`; do git checkout $b; git stash; done

After this, here are my branches:

$ git branch -a

  config_recipe
  functionaltests
  master
  parallel
  parametrize
  parametrize_data_excel
  unittesting
* unittesting1
  remotes/origin/HEAD -> origin/master
  remotes/origin/config_recipe
  remotes/origin/functionaltests
  remotes/origin/master
  remotes/origin/parallel
  remotes/origin/parametrize
  remotes/origin/parametrize_data_excel
  remotes/origin/unittesting
  remotes/origin/unittesting1

Mine goes physical, cutting out the initial remotes/origin/ and then filtering for space delimiters. Arguably, I could just have greped out HEAD and be done with one cut, but I'll leave that for the comments.

Please notice that your current branch is now the last on the list. If you don't know why that is, you're in a tight spot there. Just git checkout whatever you want now.

I needed to do exactly the same. Here is my Ruby script.

#!/usr/bin/env ruby

local = []
remote = {}

# Prepare
%x[git reset --hard HEAD]
%x[git checkout master] # Makes sure that * is on master.
%x[git branch -a].each_line do |line|
  line.strip!
  if /origin\//.match(line)
     remote[line.gsub(/origin\//, '')] = line
   else
     local << line
   end
end
# Update 
remote.each_pair do |loc, rem|
  next if local.include?(loc)
  %x[git checkout --track -b #{loc} #{rem}]
end
%x[git fetch]

This variation will clone a remote repo with all branches available locally without having to checkout each branch one by one. No fancy scripts needed.

Make a folder with the same name of the repo you wish to clone and cd into for example:

mkdir somerepo
cd somerepo

Now do these commands but with actual repo usersname/reponame

git clone --bare git@github.com:someuser/somerepo.git .git
git config --bool core.bare false
git reset --hard
git branch

Voiala! you have all the branches there!

To create a "full" backup of all branches+refs+tags+etc stored in your git host (github/bitbucket/etc), run:

mkdir -p -- myapp-mirror
cd myapp-mirror
git clone --mirror https://git.myco.com/group/myapp.git .git
git config --bool core.bare false
git config --bool core.logAllRefUpdates true
git reset --hard # restore working directory

This is compiled from everything I've learned from other answers.

You can then use this local repo mirror to transition to a different SCM system/git host, or you can keep this as a backup. It's also useful as a search tool, since most git hosts only search code on the "main" branch of each repo, if you git log -S"specialVar", you'll see all code on all branches.

Note: if you want to use this repo in your day-to-day work, run:

git config --unset remote.origin.mirror

WARNING: you may run into strange issues if you attempt to use this in your day-to-day work. If your ide/editor is doing some auto-fetching, your local master may update because, you did git clone --mirror. Then those files appear in your git staging area. I actually had a situation where I'm on a local feature branch.. that branch has no commits, and all files in the repo appear in the staging area. Just nuts.

This solution worked for me to "copy" a repository to another one:

git merge path/to/source.git --mirror
cd source.git
git remote remove origin
git remote add origin path/to/target.git
git push origin --all
git push origin --tags

On target repository I can see the same branches and tags than the origin repo.

Here, I wrote you a nice function to make it easily repeatable

gitCloneAllBranches() { # clone all git branches at once easily and cd in
  # clone as "bare repo"
  git clone --mirror $1
  # rename without .git extension
  with_extension=$(basename $1)
  without_extension=$(echo $with_extension | sed 's/.git//')
  mv $with_extension $without_extension
  cd $without_extension
  # change from "bare repository" to not
  git config --bool core.bare false
  # check if still bare repository if so
  if [[ $(git rev-parse --is-bare-repository) == false ]]; then
    echo "ready to go"
  else
    echo "WARNING: STILL BARE GIT REPOSITORY"
  fi
  # EXAMPLES:
  # gitCloneAllBranches https://github.com/something/something.git
}

This is what I do whenever I need to bring down all branches. Credits to Ray Villalobos from Linkedin Learning. Try cloning all branches including commits:

mkdir -p -- newproject_folder
cd newproject_folder
git clone --mirror https://github.com/USER_NAME/RepositoryName.git .git
git config --bool core.bare false
git reset --hard

A better alternative solution for developers using Visual Studio Code is to use Git Shadow Extension.

This Visual Studio Code extension allows cloning repository content and directories, that can be filtered by branch name or commit hash. That way, branches or commits can be used as boilerplates/templates for new projects.

Here's a cross-platform PowerShell 7 function adapted from the previous answers.

function Invoke-GitCloneAll($url) {
    $repo = $url.Split('/')[-1].Replace('.git', '')
    $repo_d = Join-Path $pwd $repo
    if (Test-Path $repo_d) {
        Write-Error "fatal: destination path '$repo_d' already exists and is not an empty directory." -ErrorAction Continue
    } else {
        Write-Host "`nCloning all branches of $repo..."
        git -c fetch.prune=false clone $url -q --progress &&
        git -c fetch.prune=false --git-dir="$(Join-Path $repo_d '.git')" --work-tree="$repo_d" pull --all
        Write-Host "" #newline
    }
}

Note: -c fetch.prune=false makes it include stale branches that would normally be excluded. Remove that if you're not interested in it.


You can make this work with PowerShell 5.1 (the default in Windows 10) by removing && from the function, but that makes it try to git pull even when the previous command failed. So, I strongly recommend just using the cross-platform PowerShell it's always bugging you about trying.

Do a bare clone of the remote repository, save the contents to a .git directory

git clone --bare remote-repo-url.git localdirname/.git

(A bare git repository, created using git clone --bare or git init --bare, is a storage repository, it does not have a working directory, you cannot create or modify files there.)

Change directory to your local directory

cd localdirname

Make your git repository modifiable

git config --bool core.bare false

Restore your working directory

git reset --hard

List all your branches

git branch -al

How to create a local branch for each branch on remote origin matching pattern.

#!/bin/sh
git fetch --all
git for-each-ref --format='%(refname:short)' refs/remotes/origin/pattern |\
    sed 's@\(origin/\)\(.*\)@\2\t\1\2@' |\
    xargs -n 2 git branch --track

All remote references (branches/tags) are fetched and then local references are created. Should work on most systems, fast, without checking out the index or relying on bashisms.

allBranches

Script to download all braches from a Git project

Installation:

sudo git clone https://github.com/marceloviana/allBranches.git && sudo cp -rfv allBranches/allBranches.sh /usr/bin/allBranches && sudo chmod +x /usr/bin/allBranches && sudo rm -rf allBranches

Ready! Now just call the command (allBranches) and tell the Git project directory that you want to download all branches

Use

Example 1:

~$ allBranches /var/www/myproject1/

Example 2:

~$ allBranches /var/www/myproject2/

Example 3 (if already inside the project directory):

~$ allBranches ./

or

~$ allBranches .

View result:

git branch

Reference:

Repository allBranches GitHub: https://github.com/marceloviana/allBranches

If you use Bitbucket, you can use import Repository. This will import all Git history (all the branches and commits).

Related