如何克隆所有远程分支?

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个回答

5166

首先,克隆一个远程Git仓库并进入其中:cd

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

接下来,查看您存储库中的本地分支:

$ git branch
* master

但是你的代码仓库中可能隐藏着其他分支! 使用-a标志可以查看它们:

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

要快速查看上游分支,请直接检出它:

$ 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'

这里的“新分支”仅意味着该分支是从索引中接收并为您本地创建的。正如前面的一行所告诉您的那样,正在设置该分支以跟踪远程分支,通常意味着 origin/branch_name 分支。

您的本地分支现在应显示为:

$ git branch
* experimental
  master

使用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

此时情况变得相当复杂,所以运行gitk以查看正在发生的事情:

$ gitk --all &

148
有什么方法可以自动创建所有远程分支,例如 origin/experimental 的 experimental 分支? - Cristian Ciupitu
62
Cristian曾经为每个'origin/foo'分支都创建一个'foo'分支,但这导致了两个问题:(1)他有很多非常陈旧的跟踪分支,这些分支与相应的远程分支相比还要落后许多,(2)在旧版本的git中,运行'git push'会尝试将所有本地分支推送到远程,即使这些分支已经过时。因此,现在他只保留那些他正在积极开发的本地分支,并直接访问origin / *分支以获取相关信息。(也可以使用shell脚本来解析'git branch -a'输出的结果。) - emk
51
"git fetch <origin-name> <branch-name>" 将该分支在本地下载到您的计算机上。 - user67627
169
回答不错,但有点偏离问题。我正在寻找一个一行命令来检出所有远程分支。 - cmcginty
36
这个问题是关于克隆所有远程分支,而不是检出它们。正如我之前提到的,你真的不想建立比必要更多的本地跟踪分支,因为当它们变得非常陈旧时,会带来麻烦。 - emk
显示剩余23条评论

928

如果您有多个远程分支需要一次性获取,请执行以下操作:

git pull --all

现在您可以根据需要检出任何分支,而无需访问远程存储库。

注意:这不会创建任何未签出分支的工作副本,这就是问题所问的。要做到这一点,请参见


13
如果我运行 git clone,我会在本地有一个主分支和10个“远程”分支。因此,Gabe给出的答案非常有帮助,回答了这个问题。 - basZero
55
这将仅获取已在本地添加的远程分支,而不是任何远程分支。 - jujule
35
第一个命令是多余的。只需使用 git pull --all 就可以完成相同的操作——它只不过不会重复抓取。infosec812 是正确的,这并没有回答问题。我想知道这是如何获得这么多赞的。 - Sven Marnach
63
这一点都没有帮助,它没有拉取除已有分支之外的任何远程分支。 - Avinash R
14
这不是第一次出现答案明显错误却因为众人投赞成票而受到认可的情况。这些人可能没有理解问题和/或回答,或者是通过谷歌搜索到了与原始作者的问题不同的东西,这样的“答案”无意中解决了他们的问题。遗憾的是,没有有效的标记来指示未回答问题的答案,唯一的方法是降低它们的投票数,但在某些情况下显然并不奏效,所以这样的噪音似乎会永远存在 :( - 9ilsdx 9rvj 0lo
显示剩余10条评论

552

这个Bash脚本帮了我一个忙:

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

这将为所有远程分支创建跟踪分支,除了主分支(您可能是从原始克隆命令中获取的)。我认为您仍然需要执行一个

git fetch --all
git pull --all

为确保操作正确。

一行代码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
如往常一样:在复制rm -rf universe之前,请先在您的设置中进行测试,因为我们知道它的意义。

感谢用户cfi提供一行代码


28
这个解决方案已经非常接近完美了。唯一让它更好的是,如果这个功能能够作为 Git 的内置选项来实现。 - Deven Phillips
67
"一行代码": 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请在复制前测试后再使用,以免出错。该命令会列出所有 Git 分支并创建本地跟踪分支。 - cfi
6
这个命令会将远程的功能分支创建为普通分支(而非功能分支),如何修复? - Alex2php
6
如果您在分支名称中遇到“/”的问题,下面有一个使用Git别名的解决方案。请查看“nobody”在“2013年5月15日11:02回答”的答案。 - wemu
14
我只是修剪“remotes/origin/”,以保留命名空间:for BRANCH in $(git branch -a | grep remotes | grep -v HEAD | grep -v master); do git branch --track "${BRANCH#remotes/origin/}" "${BRANCH}"; done - kgadek
显示剩余14条评论

499

使用--mirror选项似乎可以正确地复制remote跟踪分支。 但是,它会将仓库设置为裸仓库,因此您之后必须将其转换回普通仓库。

git clone --mirror path/to/original path/to/dest/.git
cd path/to/dest
git config --bool core.bare false
git checkout anybranch

参考资料:Git常见问题:如何克隆带有所有远程跟踪分支的存储库?


8
尽管这个回答没有任何投票,但实际上它似乎是一个相当不错的答案。这样做有什么缺陷吗?在运行这些命令后,我不得不明确地检出一个分支。 - loop
43
结合使用 git push --mirror 命令,正是我在从 github.com 迁移到 github 企业版时所需要的来创建远程 git 存储库的精确副本。谢谢! - Jacob Fike
7
@Dave:在最后一个命令中添加一个最终的git checkout,以最终检出已克隆存储库上当前分支的头部。这是一个很好的答案,迄今为止最好的。勇敢一点,最终我们会把你推到顶端 :-) - cfi
8
git clone --mirror非常适合用于备份您的git代码库 ^_^ - TrinitronX
5
使用这些步骤后,我的 CLI 从 [master] 变成了 [GIT_DIR!],最终的 checkout 操作无法完成。更新:我犯了一个错误。我克隆到了 /path/to/dest.git,而应该是 /path/to/dest/.git。然后当我取消 bare 模式时,我的 CLI 显示为 [master +0 ~0 -116 ~]。但是在执行 git checkout master 后,它做了很多工作,最终变成了 [master],看起来成功了! - Max Cascone
显示剩余16条评论

249

不需要使用复杂的“git checkout -b somebranch origin/somebranch”语法,你可以轻松地切换到一个分支。只需执行以下操作:

git checkout somebranch

Git会自动处理正确的事情:

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

Git会检查是否在恰好一个远程仓库中存在同名的分支,如果存在,则跟踪该分支的方式与您明确指定其为远程分支时相同。这是来自于 Git 1.8.2.1 的 git-checkout man 页面。

如果没有找到<branch>,但存在恰好一个跟踪分支与之匹配的远程分支(称其为<remote>),则视为等效于

$ git checkout -b <branch> --track <remote>/<branch>

2
因此,如果您checkout的分支名称与远程分支的名称相同(即“/”后面的所有内容),那么git将创建一个同名的分支,“跟踪”该远程分支?通过跟踪,我们的意思是:git pushgit pull等操作将在该远程分支上执行?如果这是正确的,请用更多的信息扩展您的答案,因为我同意@Daniel的观点,这个答案值得更多的声望。 - Gerard Roche
5
@BullfrogBlues,对于你的所有问题,答案似乎都是肯定的(我正在使用git v1.7.7.4版本)。我同意这个行为应该更加被知晓。(在这个版本的git手册中没有介绍它。)实际上,我不喜欢这种行为,我宁愿得到一个错误提示,然后显式地说出git checkout --track origin/somebranch - dubiousjim
4
@dubiousjim:实际上,这在手册中有说明。 git-checkout(1)说:“如果找不到<branch>,但确实存在一个跟踪分支在恰好一个远程(称其为<remote>),其名称与之匹配,则视为等同于'git checkout -b <branch> --track <remote>/<branch>'"(Git V.1.8.1.1)。 - sleske
1
我们需要的是 $ git pull * <remote>/* - 这里的“*”是通配符,因此它会拉取所有分支,包括尚未在本地系统上的分支。如何做到这一点?难道我们真的应该检出/拉取每个分支才能将代码拉到我们的本地系统吗? - JosephK
1
这完全没有回答问题。 - reducing activity
显示剩余2条评论

102

关于,

git checkout -b experimental origin/experimental

使用

git checkout -t origin/experimental

或者更冗长但更易记的方式
git checkout --track origin/experimental

从跟踪远程存储库的角度来看,可能会更好。


那么你的意思是第二个形式只是更容易记住,没有其他区别吗? - aderchox

92

使用别名。虽然没有原生的Git一行命令,但是你可以定义自己的别名:

git config --global alias.clone-branches '! git branch -a | sed -n "/\/HEAD /d; /\/master$/d; /remotes/p;" | xargs -L1 git checkout -t'

然后将其用作。
git clone-branches

2
谢谢。实际上,这个命令克隆了所有远程分支,而不像其他答案中的几个只克隆一个。 - FearlessHyena
1
请注意,Windows 用户需要在 git bash shell 中设置 alias,但一旦设置完成,它将在 cmdps shells 中工作。这是由于 Windows 中引用、转义和 sed 的可用性差异所致。一旦设置完成,它就可以工作,因为所有的 git 命令都是在 bash 环境中实际执行的。 - Steve Barnes
这个方法对我很有效,而其他几个答案则不行。之后,git branch 显示了原始 git 仓库中所有的 PR。 - fivestones

83

你执行的fetch应该获取所有远程分支,但不会为它们创建本地分支。如果你使用gitk,你应该看到远程分支被描述为“remotes/origin/dev”或类似的内容。

要基于远程分支创建本地分支,请执行以下操作:

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

应该返回类似这样的内容:

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

现在,当你在dev分支上时,“git pull”将会把你本地的dev更新到远程dev分支相同的位置。请注意,它将获取所有分支,但只会将你所在的分支拉到树的顶部。


16
这里不需要引用/远程分支。 git checkout -b dev origin/dev 就可以了。 - emk
4
这将始终有效:git checkout -b newlocaldev --track origin/dev。如果您想让本地分支与远程分支同名,且远程分支名称不复杂,则可以省略-b newlocaldev。使用默认的branch.autosetupmerge配置设置,并假设您没有名为dev的本地分支,这两个命令可能会执行相同的操作:git checkout -b dev origin/dev和普通的git checkout dev。最后,git checkout origin/dev不会创建新分支,而只是使您处于游离HEAD状态。 - dubiousjim
当远程分支已被删除但Git仍然无法确认其已被删除时会发生什么?这假定您已更新并且git branch -a继续将其列为远程分支。 - jww
2
我们要为数十个分支做这个吗? - JosephK

75

这是最佳的方法:

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

此时,您已经拥有了远程仓库的完整副本,包括所有分支(使用 git branch 进行验证)。如果您的远程仓库自己也有远程仓库,则可以使用--mirror而不是--bare


编辑过程中出现了一些问题。现在这个答案已经不合理了。最后一句话中提到的“--bare”在给定的命令列表中不存在。 - Cerran
1
使用以下 Dave 的回答中提到的命令 'git config --bool core.bare false' 而不是 'git config unset core.bare' 可以完成任务。 - Confused Vorlon
1
实际上是 git config --unset core.bare ... 对我来说,这似乎是此处所有答案中最干净的解决方案。可惜它没有得到太多的赞... - Dirk Hillbrecht
1
感谢@ChrisSim,我同意git config --bool core.bare false。这就是为什么我推荐Dave的答案。你对Dave的答案有什么看法?干杯! - oHo
3
这绝对是最好的答案,但是@FedericoCapaldo 给出了回答,具体说明了这些命令正在做什么。 - unrivaledcreations
显示剩余5条评论

63

当你执行"git clone git://location"命令时,会拉取所有的分支和标签。

为了在特定的远程分支上进行操作,假设它是origin远程:

git checkout -b branch origin/branchname

4
感谢你的留言“所有分支和标签都已获取”。我本来想评论你的答案是错误的,但是我检查了一下发现你是完全正确的。所以从某种意义上说,你提供了最简短的答案 - 如果你克隆了,你已经拥有它了。不错。你可以尝试添加:尝试 $ git branch -a 命令来了解哪些远程分支已经可用。 - Jan Vlcinsky
也可以看一下我发布的答案。如果你知道你想要在许多远程分支上本地工作而不必逐个检出它们,那么这可能会有所帮助。 - lacostenycoder
1
请问您能否解释一下 git checkout -b master origin/mastergit checkout --track origin/master 之间的区别呢? - aderchox
2
@aderchox 现在我想没有。 - elmarco

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