How to fetch all Git branches

后端 未结 30 1011
情书的邮戳
情书的邮戳 2020-11-22 09:38

I cloned a Git repository, which contains about five branches. However, when I do git branch I only see one of them:

$ git branch
* master


        
相关标签:
30条回答
  • 2020-11-22 09:52

    You can fetch all the branches by:

    git fetch --all
    

    or:

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

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


    To pull all the branches, use:

    git pull --all
    

    If above won't work, then precede the above command with:

    git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
    

    as the remote.origin.fetch could support only a specific branch while fetching, especially when you cloned your repo with --single-branch. Check this by: git config remote.origin.fetch.

    After that you should be able to checkout any branch.

    See also:

    • How to fetch all remote branches?
    • How to clone all remote branches in Git?

    To push all the branches to the remote, use:

    git push --all
    

    eventually --mirror to mirror all refs.


    If your goal is to duplicate a repository, see: Duplicating a repository article at GitHub.

    0 讨论(0)
  • 2020-11-22 09:54

    I wrote a little script to manage cloning a new repo and making local branches for all the remote branches.

    You can find the latest version here:

    #!/bin/bash
    
    # Clones as usual but creates local tracking branches for all remote branches.
    # To use, copy this file into the same directory your git binaries are (git, git-flow, git-subtree, etc)
    
    clone_output=$((git clone "$@" ) 2>&1)
    retval=$?
    echo $clone_output
    if [[ $retval != 0 ]] ; then
        exit 1
    fi
    pushd $(echo $clone_output | head -1 | sed 's/Cloning into .\(.*\).\.\.\./\1/') > /dev/null 2>&1
    this_branch=$(git branch | sed 's/^..//')
    for i in $(git branch -r | grep -v HEAD); do
      branch=$(echo $i | perl -pe 's/^.*?\///')
      # this doesn't have to be done for each branch, but that's how I did it.
      remote=$(echo $i | sed 's/\/.*//')
      if [[ "$this_branch" != "$branch" ]]; then
          git branch -t $branch $remote/$branch
      fi
    done
    popd > /dev/null 2>&1
    

    To use it, just copy it into your git bin directory (for me, that’s C:\Program Files (x86)\Git\bin\git-cloneall), then, on the command line:

    git cloneall [standard-clone-options] <url>
    

    It clones as usual, but creates local tracking branches for all remote branches.

    0 讨论(0)
  • 2020-11-22 09:54

    We can put all branch or tag names in a temporary file, then do git pull for each name/tag:

    git branch -r | grep origin | grep -v HEAD| awk -F/ '{print $NF}' > /tmp/all.txt
    git tag -l >> /tmp/all.txt
    for tag_or_branch in `cat /tmp/all.txt`; do git checkout $tag_or_branch; git pull origin $tag_or_branch; done
    
    0 讨论(0)
  • 2020-11-22 09:54

    To avoid the error message 'fatal: A branch named 'origin/master' already exists.', you may try my solution:

    git branch -r | grep -v '\->'  | grep -v `git branch | awk '/\*/ { print $2; }'`| while read remote; do git branch --track "${remote#origin/}" "$remote"; done
    
    0 讨论(0)
  • 2020-11-22 09:55

    You can fetch all branches from all remotes like this:

    git fetch --all
    

    It's basically a power move.

    fetch updates local copies of remote branches so this is always safe for your local branches BUT:

    1. fetch will not update local branches (which track remote branches); if you want to update your local branches you still need to pull every branch.

    2. fetch will not create local branches (which track remote branches), you have to do this manually. If you want to list all remote branches: git branch -a

    To update local branches which track remote branches:

    git pull --all
    

    However, this can be still insufficient. It will work only for your local branches which track remote branches. To track all remote branches execute this oneliner BEFORE git pull --all:

    git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
    

    TL;DR version

    git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
    git fetch --all
    git pull --all
    

    (It seems that pull fetches all branches from all remotes, but I always fetch first just to be sure.)

    Run the first command only if there are remote branches on the server that aren't tracked by your local branches.

    P.S. AFAIK git fetch --all and git remote update are equivalent.



    Kamil Szot's comment, which folks have found useful.

    I had to use:

    for remote in `git branch -r`; do git branch --track ${remote#origin/} $remote; done
    

    because your code created local branches named origin/branchname and I was getting "refname 'origin/branchname' is ambiguous whenever I referred to it.

    0 讨论(0)
  • 2020-11-22 09:57

    Here's something I'd consider robust:

    • Doesn't update remote tracking for existing branches
    • Doesn't try to update HEAD to track origin/HEAD
    • Allows remotes named other than origin
    • Properly shell quoted
    for b in $(git branch -r --format='%(refname:short)'); do
      [[ "${b#*/}" = HEAD ]] && continue
      git show-ref -q --heads "${b#*/}" || git branch --track "${b#*/}" "$b";
    done
    git pull --all
    

    It's not necessary to git fetch --all as passing -all to git pull passes this option to the internal fetch.

    Credit to this answer.

    0 讨论(0)
提交回复
热议问题