如何在Git中克隆单个分支?

1018

我有一个本地的Git仓库在~/local_repo目录下。它有几个分支:

$ git branch
* master
  rails
  c
  c++

为了克隆本地仓库,我执行以下操作:

$ git clone ~/local_repo new_repo
Initialized empty Git repository in /home/username/new_repo/.git/

new_repo的主分支指向local_repo的主分支,我可以推送/拉取。

但是我无法克隆另一个分支。我只想拉取我想要的分支(例如rails),这样新的存储库就有一个默认情况下将推送到和从local_reporails分支中拉取的master分支。如何实现这一目标?也许可以使用local_repo跟踪local_repo的主分支或类似的功能?


git branch -a 显示什么? - Jakub Narębski
5
“不带 --track 选项,使用 git checkout -b newbranch origin/branchiwant 命令是否更好?” - VonC
4
我认为你试图做的那件事是个坏主意。为不同的项目使用不同的代码仓库,分支是另一回事。请注意区分。 - innaM
1
@rodarmor,我认为你想做的事情是一个好主意,我也有同样的问题。 - Paul Du Bois
这更多是一个观点问题。谷歌将所有代码保存在单一代码库中。话虽如此,我同意@innaM的看法。尤其是在试图简化版本控制操作时,这种类型的工作流程很难管理。 - Jake Henningsgaard
显示剩余3条评论
27个回答

1136
注意:实际上,git1.7.10(2012年4月)只允许你克隆一个分支:
# clone only the remote primary HEAD (default: origin/master)
git clone <url> --single-branch

# as in:
git clone <url> --branch <branch> --single-branch <folder>

注意:
  • <url> 是远程仓库的URL,不是克隆的分支
  • <folder> 是您想要克隆存储库的本地文件夹

您可以在t5500-fetch-pack.sh中看到它:

test_expect_success 'single branch clone' '
  git clone --single-branch "file://$(pwd)/." singlebranch
'

Tobu comments 表示:

当进行浅克隆时,这是默认的。
这使得 git clone --depth 1 成为节省带宽的最简单方法。

自 Git 1.9.0(2014年2月)以来,浅克隆支持数据传输(推送/拉取),因此该选项现在更加有用。
请参见 "Is git clone --depth 1 (shallow clone) more useful than it makes out?"。


"

撤销"浅克隆"的方法详见 "将浅克隆转换为完整克隆" (git 1.8.3+)

"
# unshallow the current branch
git fetch --unshallow

# for getting back all the branches (see Peter Cordes' comment)
git config remote.origin.fetch refs/heads/*:refs/remotes/origin/*
git fetch --unshallow

正如Chris所评论:

the magic line for getting missing branches to reverse --single-branch is (git v2.1.4):

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

在 Git 2.26(2020年第一季度)中,“git clone --recurse-submodules --single-branch”现在在克隆子模块时使用相同的单分支选项。

请参见commit 132f600commit 4731957(由Emily Shaffer (nasamuffin)于2020年2月21日提交)。
(由Junio C Hamano -- gitster --于2020年3月5日合并至commit b22db26

clone: 在 --recurse-submodules 期间传递 --single-branch

签署者:Emily Shaffer
确认者:Jeff King

以前,执行 "git clone --recurse-submodules --single-branch" 会导致子模块克隆所有分支,即使超级项目只克隆了一个分支。

通过子模块帮助程序框架传递 --single-branch,以便稍后将其用于 'clone'。


114
git clone <url> --branch <branch> --single-branch <folder> 这个命令非常好用。 - Alexander
2
是的,我认为现在是时候更新被接受的答案了 :) 这确实“像魔法一样运作”。 - kumarharsh
8
在执行浅层克隆时,这个含义是隐含的。这使clone --depth 1 成为节省带宽最简单的方法。 - Tobu
1
感谢您提供如何撤销的说明 - 这正是我来这里想了解的。 - Sam Sehnert
4
完整的 Peter Cordes 更正是:获取缺失分支并反转“--single-branch”的魔术命令是 git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/*,然后运行 git fetch --unshallow(适用于 git v2.1.4)。 - Chris
显示剩余14条评论

698

有一种方法可以执行以下操作。

git clone user@git-server:project_name.git -b branch_name /your/folder

在你选择的分支中,branch_name 是你选择的分支,"/your/folder" 是该分支的目标文件夹。这将会包含其他分支,使你可以在分支之间进行合并。

更新:

从 Git 1.7.10 开始,现在可以这样做。

git clone user@git-server:project_name.git -b branch_name --single-branch /your/folder

37
这个方法可以实现,但会获取所有分支。请参考@frerich=raabe的回答。 - cdunn2001
3
谢谢你。在我的情况下只需添加“-b 分支名称”就可以了。这为我节省了很多时间。 - PhatHV
是的,它完美地运作了!我更喜欢使用TFS,对于我的个人项目一直在使用git。关于git分支,我之前做错了,很高兴知道这种简单的方法,看起来非常完美!再次感谢!已经点赞了,如果可能的话,我会给+100 :) - k25
14
您也可以添加 --single-branch 参数,仅获取与此分支相关的历史记录,而不是包含在存储库中的所有历史记录和标签。 - Mickäel A.
1
@AlexNolasco 你能否编辑答案并说明 /some/folder 是什么?谢谢 - Nabin
显示剩余2条评论

115

使用Git版本1.7.3.1(在Windows上),以下是我要做的事情($BRANCH是我想要检出的分支名称,$REMOTE_REPO是我想要克隆的远程仓库的URL):

mkdir $BRANCH
cd $BRANCH
git init
git remote add -t $BRANCH -f origin $REMOTE_REPO
git checkout $BRANCH

这种方法的优点是后续的git pull(或git fetch)调用也只会下载所需的分支。

你的脚本和这条命令有什么不同?git clone -b $BRANCH $REMOTE_REPO $BRANCH。理论上来说它们是相同的吗? - Ian Vaughan
12
一个区别在于git clone -b会像git branch -a一样给你所有的远程引用(所有的远程分支和标签)。使用我的脚本,你只会得到一个单独的引用。 - Frerich Raabe
1
当我尝试上述操作(例如使用$BRANCH="nick"),我会得到“fatal: Couldn't find remote ref refs/heads/nick”的错误提示。对我来说似乎不起作用... - Nick
3
注意,即使没有 -f 参数也可以使用 -t $BRANCH,它会立即获取。然后,git fetch origin 会获取内容,git checkout $BRANCH 会建立本地分支并检出。当您需要在获取之前配置远程时,这非常有用,例如 git config remote.origin.uploadpack=/bin/upload-pack - cdunn2001
1
由于我使用的是“旧版”企业版git(1.6.0.2),所以我只能使用上述解决方案。我和@Nick遇到了同样的问题。执行git branch -a命令会显示origin/$BRANCH。使用git checkout origin/$BRANCH命令可以解决这个问题。 - dr jerry

33

您可以尝试冗长的方法:

mkdir newrepo.git
cd newrepo.git
git init
git remote add origin file:///path/to/original
git fetch origin branchiwant:refs/remotes/origin/branchiwant
git checkout -b branchiwant --track origin/branchiwant

这段代码的作用是:

  • 创建并初始化一个空的Git仓库。
  • 将原始仓库添加为名为origin的远程仓库。
  • 从名为origin的远程仓库中仅获取您需要的分支。
  • 创建并检出一个新分支,该分支已设置为跟踪您刚克隆的源分支。

希望这符合您的要求。


git remote add 命令的参数位置颠倒了,但是我无法让 checkout 命令正常工作。"git checkout origin/rails" 给出了 "error: pathspec 'origin/rails' did not match any file(s) known to git." 的错误提示,而另一种方式则给出了 "fatal: git checkout: updating paths is incompatible with switching branches." 的致命错误提示。 - Casey Rodarmor
@rodarmor:已经更正了git远程命令,谢谢。你能粘贴一下git branch -r的输出吗? - jkp
@rodarmor:我已经更正了这个例子,它绝对可行(已测试)。希望有所帮助(如果你喜欢的话,可以在测试后接受它;) - jkp
-b开关是相对较新的。我上次在Debian Squeeze上运行它时,好像还没有这个选项。 - sehe
最后一个命令应该是:git checkout -b branchiwant --track remotes/branchiwant。 - KONG
显示剩余2条评论

33
git clone <url> --branch <branch> --single-branch

只需输入URL和分支名称。


27

您可以使用以下命令来完成:

git clone -b branch_name --single-branch project_url local_folder_to_clone_in

2
完美地工作了,我实际上在 Source Tree 中克隆单个分支时遇到了问题,因此我手动完成了它。 - azhar22k

20

来自git-clone man page

--single-branch 在克隆时很有用,记得与--branch <branch name>一起使用,否则只会克隆远程主要HEAD(默认为master)

始终记得按Ctrl+F5阅读最新源代码,而不是缓存中的代码:-)(我没有这样做,所以很长一段时间都不知道这个选项。)


1
git clone <url> --branch <branch> --single-branch <folder>使用上述命令可以将指定分支的代码克隆到指定文件夹中。 - Shridutt Kothari

10

只克隆一个分支。这是最简单的方法:

git clone -b BRANCH_NAME --single-branch git@bitbucket.org:___/PROJECTNAME.git

7

这里有足够的答案提到:

  1. Download 1 branch (with the --single-branch part):

    # (We'll refer to this as "the 1st command" below.)
    # 1. Clone ONLY `branch_name`, then check it out. The `--single-branch` part
    #    means that ONLY `branch_name` is cloned, fetched, pulled, and
    #    tracked. _No other remote branches will be cloned to your PC
    #    whatsoever._
    git clone -b branch_name --single-branch \
    https://github.com/some_project/some_project.git
    

    ...or some version of that, and a few which mention just:

  2. Download all branches (withOUT the --single-branch part):

    # (We'll refer to this as "the 2nd command" below.)
    # 2. Clone ALL remote branches, then `git checkout` the `branch_name`
    #    branch.
    git clone -b branch_name \
    https://github.com/some_project/some_project.git
    

但是,我想稍微解释一下这两件事,并展示一个更熟悉的等效命令组合,这样我们可以看到每个命令在底层发生了什么。

假设您在GitHub上有一个远程repo,链接为https://github.com/micronucleus/micronucleus.git,有远程分支masterversion_2.5(这是一个真实的例子,您可以立即运行)。

对第二个以上命令的详细说明:

第二个命令git clone -b version_2.5 https://github.com/micronucleus/micronucleus.git)克隆所有远程分支到您的本地PC,但是然后检出version_2.5分支而不是master分支。该命令相当于执行以下操作:

git clone https://github.com/micronucleus/micronucleus.git
cd micronucleus  # cd into the repo you just cloned
git checkout version_2.5
# To be pedantic, also delete the local `master` branch since
# technically it won't exist yet since you haven't yet checked
# it out with `git checkout master`, which would create it from
# your locally-stored remote-tracking branch, `origin/master`
git branch -d master

-b version_2.5 部分自动为我们检出了 version_2.5 分支,而不是 master

git branch -a 显示我们将所有分支都克隆到了本地电脑。在这里,您可以看到我们正在使用的本地分支 version_2.5,以及存储在本地的远程跟踪分支 origin/HEAD(指向 origin/master),加上 origin/masterorigin/version_2.5

$ git branch -a
* version_2.5
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/version_2.5

我们还可以查看我们的fetch引用。您可以打开.git/config文件直接查看,或者只需运行git config remote.origin.fetch:
$ git config remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*

您可以看到上面我们的git fetch命令(也由git pull触发,因为它相当于git fetch && git merge)被配置为获取origin远程所有分支的所有头。我不是这方面的专家,但我认为这就是+refs/heads/*:refs/remotes/origin/*的含义。

以上第一个命令的详细说明:

第一个命令git clone -b version_2.5 --single-branch https://github.com/micronucleus/micronucleus.git)仅克隆并检出了您本地PC上的version_2.5分支。这个命令等同于(至少在最终结果上是这样,除了它在开始时只克隆了一个分支而不是全部):
git clone https://github.com/micronucleus/micronucleus.git
cd micronucleus  # cd into the repo you just cloned
git checkout version_2.5

# Delete ALL other branches, including remote-tracking ones, which are not the 
# `version_2.5` branch:
# One local branch
git branch -d master
# ALL other locally-stored remote-tracking branches
git branch -dr origin/HEAD 
git branch -dr origin/master

# Fix your `.git/config` file so that `git fetch` does the right thing, fetching
# ONLY the `version_2.5` branch head from the `origin/version_2.5` remote branch:
git config remote.origin.fetch \
"+refs/heads/version_2.5:refs/remotes/origin/version_2.5"

"

-b version_2.5 部分导致默认情况下检出了 version_2.5 分支,而不是之前解释的 master 分支。而 --single-branch 部分导致:

  1. 没有其他分支被克隆到我们的电脑上,和
  2. git fetch 被配置为在调用 git fetchgit pull不会获取任何其他分支!

这个命令真正地只克隆了我们想要的一个分支,就是这样!

git branch -a 显示只有 version_2.5 分支被克隆和检出。我们可以通过 * 看到哪个分支被检出,并且我们还看到了一个本地存储的远程跟踪分支 origin/version_2.5:

"
$ git branch -a
* version_2.5
  remotes/origin/version_2.5

我们还可以查看我们的fetch引用。您可以打开.git/config文件直接查看,或者只需运行git config remote.origin.fetch:
$ git config remote.origin.fetch
+refs/heads/version_2.5:refs/remotes/origin/version_2.5

你可以看到,我们的git fetch命令只会从origin/version_2.5远程分支获取version_2.5分支头。就是这样!请注意,不会获取任何其他远程分支。

总结:

因此,现在你知道使用-b branch_name基本上只是确保在克隆后检出branch_name分支,但仍会克隆所有远程分支,而添加--single-branch则确保仅克隆、提取、拉取和跟踪branch_name不会克隆任何其他远程分支到你的电脑中。

个人而言,我更喜欢仅使用-b branch_name选项,因为我希望将所有分支克隆到我的本地电脑。唯一的例外可能是在一个巨大的共享单库上,该库有数十个甚至数百或数千个远程分支。在这种情况下,只需使用-b branch_name --single-branch来克隆您关心的主要分支即可完成。比如,在一个巨大的单库中下载50 GiB的数据,对于master分支来说,要比下载200 GiB的数据好,因为你也可以拥有你的同事正在工作的2000个分支!

参考资料:

  1. 仅克隆一个分支
  2. 如何停止跟踪Git中的远程分支?

7
git clone --branch <branchname> <remote-repo-url>

或者
git clone -b <branchname> <remote-repo-url>

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