Peter Coulton
Peter Coulton

Reputation: 55829

How do I clone all remote branches?

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

Upvotes: 4823

Views: 1858736

Answers (30)

Dut A.
Dut A.

Reputation: 1178

I wanted a repeatable way and so wrote this Zsh function (not tested against Bash but may be compatible).

Add it to .zshrc or .bashrc and call it from anywhere those settings are loaded.

function clone_repo_all_branches() {
    repo_url="$1"
    if [[ -z "$repo_url" ]]; then
        echo "Error: No repository URL provided."
        return 1
    fi

    # Extract the repository name from the URL ('.git' extension is optional)
    repo_name=$(echo "$repo_url" | sed -E 's|.*/(.*)\.git$|\1|; s|.*/||')
    echo "repo name: $repo_name"
    rm -rf "$repo_name" # Remove the repository directory if it already exists

    # Ensure .git is appended if not already present
    if [[ ! "$repo_url" =~ \.git$ ]]; then
        repo_url="${repo_url}.git"
    fi

    git clone --no-single-branch "$repo_url" || return # Clone the repository without checking out a single branch
    cd "$repo_name" || return                          # Change to the cloned repository directory

    git fetch --all
    git branch -r | grep -v '\->' | while read -r remote_branch; do
        local_branch="${remote_branch#origin/}"
        git branch --track "$local_branch" "$remote_branch" 2>/dev/null || echo "Branch $local_branch already exists."
    done
    echo -e "\n---All remote branches cloned successfully.\n---\n"
}

# give it some little alias to let you be lazy when calling it
alias crab=clone_repo_all_branches

call it:

$ clone_repo_all_branches your-repo-url.git

OR

$ clone_repo_all_branches your-repo-url

OR

$ crab your-repo-url.git

OR

$ crab your-repo-url

Upvotes: 0

Pradipta
Pradipta

Reputation: 241

Clone the repo and hop into that directory

git clone <repo>
cd repo

fetch all the branches from the remote repository

git fetch --all

Now checkout all of them:

for branch in `git branch -r|grep -v '\->'`;do git checkout --track $branch;done

Upvotes: 2

a Learner
a Learner

Reputation: 5042

What I used is:

1)$ git clone url
2)$ git branch -a   //lists down all branches
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/feature/remote_branch_name1
  remotes/origin/master

3)$ git checkout origin/feature/remote_branch_name1

git checkout origin/feature/remote_branch_name1
Note: switching to 'origin/feature/remote_branch_name1

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 14e5377 Updated the Folder Structure

4)$ git switch -c remote_branch_name1
Switched to a new branch 'remote_branch_name1'

Working directory got changed by above command.

5)$ git branch
* remote_branch_name1
  master

Upvotes: 1

Dimitri Lesnoff
Dimitri Lesnoff

Reputation: 382

I could not edit Bigfish answer's. He proposes a bash script which I offer to update and give a better git integration. egrep is outdated and should be replaced by grep -E.

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

You can extend git by adding this bash file as a git custom subcommand:

$ mkdir ~/.gitbin; touch ~/.gitbin/git-fetchThemAll
$ chmod u+x ~/.gitbin/git-fetchThemAll

Put the content of the bash script in git-fetchThemAll.

$ echo 'export PATH="$HOME/.gitbin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc # update PATH in your current shell
$ git fetchThemAll

If you prefer, you could use a shell alias for this oneliner by user cfi

alias fetchThemAll=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

Upvotes: 4

rapher
rapher

Reputation: 495

Just do this:

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

$ cd myproject

$ git checkout branchxyz
Branch branchxyz set up to track remote branch branchxyz from origin.
Switched to a new branch 'branchxyz'

$ git pull
Already up-to-date.

$ git branch
* branchxyz
  master

$ git branch -a
* branchxyz
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/branchxyz
  remotes/origin/branch123

You see, git clone git://example.com/myprojectt fetches everything, even the branches, you just have to checkout them, then your local branch will be created.

Upvotes: 47

emk
emk

Reputation: 60942

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 &

Upvotes: 5220

CervEd
CervEd

Reputation: 4272

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.

Upvotes: 3

Devin Rhode
Devin Rhode

Reputation: 25367

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.

Upvotes: 14

Ricardo
Ricardo

Reputation: 821

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.

Upvotes: 14

Maybe
Maybe

Reputation: 1005

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.

Upvotes: 0

ioedeveloper
ioedeveloper

Reputation: 538

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.

Upvotes: 0

M. Dhaouadi
M. Dhaouadi

Reputation: 625

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

Upvotes: -3

Albert.Qing
Albert.Qing

Reputation: 4625

#!/bin/bash
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master `; do
   git branch --track ${branch#remotes/origin/} $branch
done

These code will pull all remote branches code to the local repository.

Upvotes: 17

gringo_dave
gringo_dave

Reputation: 1482

I wrote these small PowerShell functions to be able to checkout all my Git branches, that are on origin remote.

Function git-GetAllRemoteBranches {
     iex "git branch -r"                       <# get all remote branches #> `
     | % { $_ -Match "origin\/(?'name'\S+)" }  <# select only names of the branches #> `
     | % { Out-Null; $matches['name'] }        <# write does names #>
}


Function git-CheckoutAllBranches {
    git-GetAllRemoteBranches `
        | % { iex "git checkout $_" }          <# execute ' git checkout <branch>' #>
}

More Git functions can be found in my Git settings repository.

Upvotes: 12

kenorb
kenorb

Reputation: 166793

Git usually (when not specified) fetches all branches and/or tags (refs, see: git ls-refs) from one or more other repositories along with the objects necessary to complete their histories. In other words, it fetches the objects which are reachable by the objects that are already downloaded. See: What does git fetch really do?

Sometimes you may have branches/tags which aren't directly connected to the current one, so git pull --all/git fetch --all won't help in that case, but you can list them by:

git ls-remote -h -t origin

And fetch them manually by knowing the ref names.

So to fetch them all, try:

git fetch origin --depth=10000 $(git ls-remote -h -t origin)

The --depth=10000 parameter may help if you've shallowed repository.

Then check all your branches again:

git branch -avv

If the above won't help, you need to add missing branches manually to the tracked list (as they got lost somehow):

$ git remote -v show origin

...
  Remote branches:
    master      tracked

by git remote set-branches like:

git remote set-branches --add origin missing_branch

so it may appear under remotes/origin after fetch:

$ git remote -v show origin

...
  Remote branches:
    missing_branch new (next fetch will store in remotes/origin)
$ git fetch
From github.com:Foo/Bar
 * [new branch]      missing_branch -> origin/missing_branch

Troubleshooting

If you still cannot get anything other than the master branch, check the following:

  • Double check your remotes (git remote -v), e.g.
    • Validate that git config branch.master.remote is origin.
    • Check if origin points to the right URL via: git remote show origin (see this post).

Upvotes: 8

Phil
Phil

Reputation: 216

Use commands that you can remember

I'm using Bitbucket, a repository hosting service of Atlassian. So I try to follow their documentation. And that works perfectly for me. With the following easy and short commands you can checkout your remote branch.

At first clone your repository, and then change into the destination folder. And last, but not least, fetch and checkout:

git clone <repo> <destination_folder>
cd <destination_folder>
git fetch && git checkout <branch>

That's it. Here a little more real-world example:

git clone https://[email protected]/team/repository.git project_folder
cd project_folder
git fetch && git checkout develop

You will find detail information about the commands in the documentation: Clone Command, Fetch Command, Checkout Command

Upvotes: 11

Fed
Fed

Reputation: 1885

All the answers I saw here were valid, but there is a much cleaner way to clone a repository and to pull all the branches at once.

When you clone a repository, all the information of the branches is actually downloaded, but the branches are hidden. With the command

git branch -a

you can show all the branches of the repository, and with the command

git checkout -b branchname origin/branchname

you can then "download" them manually one at a time.


However, when you want to clone a repository with a lot of branches, all the ways illustrated in previous answers are lengthy and tedious in respect to a much cleaner and quicker way that I am going to show, though it's a bit complicated. You need three steps to accomplish this:

1. First step

Create a new empty folder on your machine and clone a mirror copy of the .git folder from the repository:

cd ~/Desktop && mkdir my_repo_folder && cd my_repo_folder
git clone --mirror https://github.com/planetoftheweb/responsivebootstrap.git .git

The local repository inside the folder my_repo_folder is still empty, and there is just a hidden .git folder now that you can see with a "ls -alt" command from the terminal.

2. Second step

Switch this repository from an empty (bare) repository to a regular repository by switching the boolean value "bare" of the Git configurations to false:

git config --bool core.bare false

3. Third Step

Grab everything that inside the current folder and create all the branches on the local machine, therefore making this a normal repository.

git reset --hard

So now you can just type the command "git branch" and you can see that all the branches are downloaded.

This is the quick way in which you can clone a Git repository with all the branches at once, but it's not something you want to do for every single project in this way.

Upvotes: 29

Tebe
Tebe

Reputation: 3214

Looking at one of the answers to the question I noticed that it's possible to shorten it:

for branch in  `git branch -r | grep -v 'HEAD\|master'`; do
    git branch --track ${branch##*/} $branch;
done

But beware, if one of remote branches is named, e.g., admin_master it won't get downloaded!

Upvotes: 13

Gaui
Gaui

Reputation: 8959

None of these answers cut it, except user nobody is on the right track.

I was having trouble with moving a repository from one server/system to another. When I cloned the repository, it only created a local branch for master, so when I pushed to the new remote, only the master branch was pushed.

So I found these two methods very useful.

Method 1:

git clone --mirror OLD_REPO_URL
cd new-cloned-project
mkdir .git
mv * .git
git config --local --bool core.bare false
git reset --hard HEAD
git remote add newrepo NEW_REPO_URL
git push --all newrepo
git push --tags newrepo

Method 2:

git config --global alias.clone-branches '! git branch -a | sed -n "/\/HEAD /d; /\/master$/d; /remotes/p;" | xargs -L1 git checkout -t'
git clone OLD_REPO_URL
cd new-cloned-project
git clone-branches
git remote add newrepo NEW_REPO_URL
git push --all newrepo
git push --tags newrepo

Upvotes: 11

Haimei
Haimei

Reputation: 13005

You only need to use "git clone" to get all branches.

git clone <your_http_url>

Even though you only see the master branch, you can use "git branch -a" to see all branches.

git branch -a

And you can switch to any branch which you already have.

git checkout <your_branch_name>

Don't worry that after you "git clone", you don't need to connect with the remote repository. "git branch -a" and "git checkout <your_branch_name>" can be run successfully when you don't have an Internet connection. So it is proved that when you do "git clone", it already has copied all branches from the remote repository. After that, you don't need the remote repository. Your local already has all branches' code.

Upvotes: 35

Sam
Sam

Reputation: 1643

This isn't too complicated. Very simple and straightforward steps are as follows;

git fetch origin: This will bring all the remote branches to your local.

git branch -a: This will show you all the remote branches.

git checkout --track origin/<branch you want to checkout>

Verify whether you are in the desired branch by the following command;

git branch

The output will like this;

*your current branch
some branch2
some branch3

Notice the * sign that denotes the current branch.

Upvotes: 54

ikaruss
ikaruss

Reputation: 491

For copy-pasting into the command line:

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

For higher readability:

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

This will:

  1. check out master (so that we can delete branch we are on)
  2. select remote to checkout (change it to whatever remote you have)
  3. loop through all branches of the remote except master and HEAD 0. delete local branch (so that we can check out force-updated branches) 0. check out branch from the remote
  4. check out master (for the sake of it)

It is based on the answer of VonC.

Upvotes: 10

Camwyn
Camwyn

Reputation: 456

I was trying to find out how to pull down a remote branch I had deleted locally. Origin was not mine, and I didn't want to go through the hassle of re-cloning everything.

This worked for me:

assuming you need to recreate the branch locally:

git checkout -b recreated-branch-name
git branch -a (to list remote branches)
git rebase remotes/remote-origin/recreated-branch-name

So if I forked from gituser/master to sjp and then branched it to sjp/mynewbranch, it would look like this:

$ git checkout -b mynewbranch

$ git branch -a
  master
  remotes/sjp/master
  remotes/sjp/mynewbranch

$ git fetch (habit to always do before)

$ git rebase remotes/sjp/mynewbranch

Upvotes: 2

Jacob Fike
Jacob Fike

Reputation: 1001

Here is the best way to do this:

mkdir repo
cd repo
git clone --bare path/to/repo.git .git
git config --unset core.bare
git reset --hard

At this point you have a complete copy of the remote repository with all of its branches (verify with git branch). You can use --mirror instead of --bare if your remote repository has remotes of its own.

Upvotes: 78

Andy
Andy

Reputation: 5228

I think this does the trick:

mkdir YourRepo
cd YourRepo
git init --bare .git                       # create a bare repo
git remote add origin REMOTE_URL           # add a remote
git fetch origin refs/heads/*:refs/heads/* # fetch heads
git fetch origin refs/tags/*:refs/tags/*   # fetch tags
git init                                   # reinit work tree
git checkout master                        # checkout a branch

So far, this works for me.

Upvotes: 2

Gabe Kopley
Gabe Kopley

Reputation: 16687

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

Upvotes: 943

murphytalk
murphytalk

Reputation: 1297

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.

Upvotes: 102

webmat
webmat

Reputation: 60636

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

Upvotes: 19

Luuk Paulussen
Luuk Paulussen

Reputation: 909

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.

Upvotes: 83

Tony Barganski
Tony Barganski

Reputation: 2291

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://[email protected]
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.

Upvotes: 21

Related Questions