如何克隆所有远程分支?

4759

我在GitHub上远程追踪我的masterdevelopment分支。我该如何同时克隆这两个分支呢?


161
这里的被接受的答案(git branch -a)会展示远程仓库中的分支,但是如果你试图检出它们中的任何一个,你将处于'脱离HEAD'状态。第二个最受赞同的回答回答了另一个问题(即如何拉取所有分支,并且再次强调,这仅适用于你在本地跟踪的分支)。其中一些评论指出,你可以使用shell脚本解析git branch -a的结果来本地跟踪所有远程分支。总结:没有Git原生方法可以实现你想要的功能,而且也许这并不是一个好主意。 - Day Davis Waterbury
6
也许可以通过传统方式复制整个文件夹?scp some_user@example.com:/home/some_user/project_folder ~ 不确定这种解决方案是否适用于GitHub... - snapfractalpop
26
与其说“我已经克隆、拉取和获取了”,更好的方法是展示您执行的精确命令 - Bob Gilmore
94
“克隆”为何不是指完全的复制,这一点始终让我感到困惑。如果它是一个完全的克隆,那么所有分支不都应该是本地仓库的一部分吗?我的意思是,这不是分布式的一个重点之一吗?因此,当某个仓库消失时,您仍然拥有完整的副本。或者所谓的“远程”已经真正成为本地仓库的一部分了吗? - huggie
34
看到所有的点赞、回答、回答评论和惊人的浏览量,我认为现在是时候为此添加一个Git命令了。而你说得没错,@huggie,我的想法正是如此。 - Sнаđошƒаӽ
显示剩余9条评论
48个回答

13

看到这个问题的其中一个答案,我注意到可以将其缩短:

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

但是要注意,如果其中一个远程分支的名称为admin_master,它不会被下载!


你可以改进正则表达式,或者使用Awk代替grep,以改善过滤器以避免误报。 - tripleee
所有的分支都是'origin\my_branch_name',这并不是我想要的。 - Sнаđошƒаӽ
我以前没有见过 ${branch##*/} 这种结构 - 看起来非常有用 - 你知道在哪里可以找到更多关于它的信息吗?在 bash 中似乎找不到。谢谢。 - SaminOz

12

我编写了这些小的PowerShell函数,以便能够检出所有在origin远程的Git分支。

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>' #>
}

更多的Git功能可以在我的 Git 设置存储库中找到。


12

好的,当你克隆仓库时,所有分支都在那里...

如果你只执行git branch命令,它们会被隐藏起来...

所以如果你想要查看所有分支名称,只需简单地添加--all参数,像这样:

git branch --allgit branch -a

如果你只是切换到分支,你就得到了你需要的所有内容。

但如果在你克隆之后由其他人创建了分支,怎么办呢?

在这种情况下,只需执行:

git fetch

然后再次检查所有分支...

如果你想要同时获取并检出分支,可以执行:

git fetch && git checkout 你的分支名称

我还为你创建了以下图片,以便更好地理解:

git branch --all to get all branches


6
“你拥有它”和“你看到它”之间存在差异。当您删除远程存储库时,git branch -all将不再列出远程分支。 - Gustave

12

git clone --mirror 用于原始仓库很有效。

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

克隆所有分支的最简单方法! - david.perez

12

要创建一个包含git主机(github/bitbucket等)中存储的所有分支、引用、标签等的“完全”备份,请运行:

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

这是我从其他答案中学到的所有内容编译而来。

然后,您可以使用此本地存储库镜像来过渡到另一个SCM系统/ Git主机,或者将其保留为备份。它还可以用作搜索工具,因为大多数Git主机仅在每个存储库的“main”分支上搜索代码,如果您运行 git log -S"specialVar",则会看到所有分支上的所有代码。

注意:如果您想在日常工作中使用此存储库,请运行:

git config --unset remote.origin.mirror

警告:如果您尝试在日常工作中使用此功能,可能会遇到奇怪的问题。如果您的IDE/编辑器正在进行某些自动提取操作,则您的本地master可能会更新,因为您执行了git clone --mirror。然后这些文件将出现在您的git暂存区中。我曾经遇到过这样的情况,即我在本地功能分支上..该分支没有提交,并且仓库中的所有文件都出现在暂存区中。真是疯狂。


1
git reset --hard 看起来很可怕。这到底是要做什么?需要解释一下。例如,这个命令的主要思想/要点是什么?请通过编辑您的答案进行回复,而不是在评论中回复(不要包含“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的)。 - Peter Mortensen
3
因为这是一个全新克隆的目录,我不认为它很可怕。 - Devin Rhode
1
我承认我并不真正理解它是如何工作的,但与其他解决方案相比,它是唯一可用的,在几行命令中可以将所有分支本地下载,非常感谢。 - Francesco Orsi
如果意图是在本地创建一个包含所有分支的完整仓库副本,那么这应该被视为正确答案。git reset --hard 只是丢弃自上次提交以来的任何更改,然后将 HEAD 设置为该提交。真的一点也不可怕。参考:https://git-scm.com/docs/git-reset - Scopperloit
为什么不使用 git checkout --recurse-submodules 而不是重置呢?这样做不是更全面备份整个仓库,而不仅仅是重置单个仓库吗? - Andry
我不确定如何修改这种方法来处理子模块。说到 --recurse-submodules,你也可以将相同的 cli 选项传递到 git clone 中,但是如果你使用 --mirror,该选项将被忽略。(参见文档:https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---recurse-submodulesltpathspecgt)也许这种方法可以使用某种 git submodule foreach 'do clone --mirror' --recursive 脚本来进行递归镜像克隆?(参见文档:https://git-scm.com/docs/git-submodule#Documentation/git-submodule.txt-foreach--recursiveltcommandgt) - Devin Rhode

11

除了用户nobody的回答,其他答案都不太合适。

我在将一个仓库从一台服务器/系统移动到另一台时遇到了问题。当我克隆仓库时,它只为主分支创建了一个本地分支,因此当我推送到新的远程仓库时,只有主分支被推送。

所以我发现这两种方法非常有用。

方法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

方法二:
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

11

以下是使用 awk 的答案。如果在新的存储库上使用,此方法应该足够。

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

现有的分支将被简单检出,或声明为已经在其中,但可以添加过滤器以避免冲突。

也可以修改它,使其调用显式的git checkout -b <branch> -t <remote>/<branch>命令。

此答案遵循Nikos C.idea


或者我们可以指定远程分支。这是基于murphytalkanswer

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

当发生冲突时,它会抛出致命错误消息,但我认为它们无害。


这两个命令都可以设置别名。

参考nobodyanswer,我们可以使用以下命令来创建别名:

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) }"'

个人建议使用track-alltrack-all-branches


只是想感谢您。这个工作非常完美,而且不会遇到与克隆裸仓库相关的各种问题,例如某些拉取行为的更改等。 - mahonya

11
我正在从Udemy课程Python和Pytest的优雅自动化框架克隆一个仓库,以便稍后离线查看。我尝试下载zip文件,但这只适用于当前分支,所以这是我的建议。
我在Windows上工作,显然,我使用了Windows子系统Linux中的Ubuntu shell。克隆后,这里是我的分支:
$ 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

然后,在遇到一些git checkout的问题之后,最终对我有效的方法是:

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

接下来,这是我的分支:

$ 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

我的做法是物理删除,去掉初始的remotes/origin/,然后过滤空格分隔符。可以说,我只需要用一个cut命令就可以grepHEAD,但这个问题留给评论区讨论。
请注意,你当前的分支现在是列表中的最后一个。如果你不知道为什么会这样,那你就有些棘手了。现在只需git checkout任何你想要的即可。

这个解决方案对我很有帮助,它可以检索具有原始文件夹结构的分支。 - DanielV

10

使用易于记忆的命令

我正在使用Atlassian的代码库托管服务Bitbucket。因此,我尝试遵循他们的文档。这对我来说非常完美。使用以下简单和短的命令,您可以检出您的远程分支。

首先克隆您的代码库,然后切换到目标文件夹。最后,别忘了获取并检出:

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

就是这样。下面给出一个更实际的例子:

git clone https://username@bitbucket.org/team/repository.git project_folder
cd project_folder
git fetch && git checkout develop

您可以在文档中找到有关以下命令的详细信息: Clone 命令Fetch 命令Checkout 命令


10

用于复制粘贴到命令行中:

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

为了更高的可读性:
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

我将会:
  1. 检出主分支(以便我们可以删除所在的分支)
  2. 选择远程分支 进行检出(更改为您拥有的任何远程分支)
  3. 循环遍历所有分支,除了 master 和 HEAD 0. 删除 本地分支(以便我们可以强制更新分支) 0. 从远程检出分支
  4. 检出主分支(无意义)

它基于 VonCthe answer


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接