在git中如何仅克隆稳定版本和另一个分支?

22

我刚开始使用 Git,有一个问题想请教。我的应用程序有10个其他开发人员在上面工作,每个人都有自己的分支,比如dev_XXXXX。那么如果我克隆仓库,他们所有的代码都会被复制到我的机器上吗?如果是这样的话,我不想要。假设我的分支是dev_swamy,那么我如何只克隆稳定分支和dev_swamy分支呢?谢谢。

5个回答

27
默认情况下,git clone 会拉取所有分支,但这些分支将被存储为远程跟踪分支:例如 'dev_XXXXX' 分支将被存储为 'origin/dev_XXXXX'(完整名称为 'refs/remotes/origin/dev_XXXXX')。这些远程跟踪分支在 git branch 输出中不可见:您需要使用 git branch -r 列出远程跟踪分支(或使用 git branch -a 列出所有分支)。如果这些分支与主线没有偏离太多,它们不会占用过多的存储空间。因此,我不清楚您为什么要克隆只有选定分支。
尽管如此,如果您想要一个只包含两个选定分支的克隆,可以按照以下方式操作:
  1. First, create new empty repository

    $ mkdir repoclone
    $ cd repoclone/
    $ git init
    Initialized empty Git repository in /home/user/repoclone/.git/
    
  2. Then add your repository under the name 'origin' (just like "git clone" would name it), requesting tracking of only two branches: 'master' and 'dev_swamy', using "git remote" command. Check that it was added correctly.

    $ git remote add -t master -t dev_swamy origin user@example.com:repo.git
    $ git remote 
    origin
    $ git remote show origin
    * remote origin
      Fetch URL: user@example.com:repo.git
      Push  URL: user@example.com:repo.git
      HEAD branch: master
      Remote branches:
        master          new (next fetch will store in remotes/origin)
        dev_swamy new (next fetch will store in remotes/origin)
    

    If the stable branch is called 'stable' rather than 'master', you would have of course to modify above example. Also there is -m <branch> option if you want specified branch to be default branch in remote.

  3. Fetch from 'origin' (you could do this also by using -f option to "git remote add" above):

    $ git fetch
    remote: Counting objects: 282, done.
    remote: Compressing objects: 100% (193/193), done.
    remote: Total 282 (delta 82), reused 0 (delta 0)
    Receiving objects: 100% (282/282), 81.30 KiB | 135 KiB/s, done.
    Resolving deltas: 100% (82/82), done.
    From user@example.com:repo.git
     * [new branch]      master     -> origin/master
     * [new branch]      dev_swamy -> origin/dev_swamy
    From user@example.com:repo.git
     * [new tag]         v1.0       -> v1.0
     * [new tag]         v1.0.1    -> v1.0.1
     * [new tag]         v1.1       -> v1.1
    
  4. Set up local branch 'master' (where you would do your work) to follow 'origin/master' (to have 'origin/master' as upstream), just like "git clone" would do:

    $ git checkout -t origin/master
    Branch master set up to track remote branch master from origin.
    Already on 'master'
    

    You can repeat this for branch 'dev_swamy'.

  5. Now you can see how config file looks like. You can get exactly the same result by editing .git/config file to look like the following, and then doing "git fetch".

    $ cat .git/config  # or just open this file in your editor
    [core]
            repositoryformatversion = 0
            filemode = true
            bare = false
            logallrefupdates = true
    [remote "origin"]
            url = user@example.com:repo.git
            fetch = +refs/heads/master:refs/remotes/origin/master
            fetch = +refs/heads/dev_swamy:refs/remotes/origin/dev_swamy
    [branch "master"]
            remote = origin
            merge = refs/heads/master
    

在开始使用Git仓库之前,不要忘记向其介绍自己(即设置'user.name'和'user.email'配置变量;通常在每个用户的配置文件中)!


4
如果你克隆,所有分支中的所有修订版本都会被克隆,但是克隆的仓库默认会检出主分支。
只选择某些分支比较麻烦,因为Git并不认为你应该这样工作。你必须手动拉取分支:
mkdir repoclone
cd repoclone
git init
git remote add origin git://remote/url
git fetch origin master:master
git fetch origin dev_XXX:dev_XXX

以上是我知道的可行方法。然而,如果你想设置一个正常工作但只查看特定远程分支的git仓库?你可以很容易地做到这一点:

mkdir repoclone
cd repoclone
git init
git remote add origin git://remote/url

# now open .git/config for editing in your editor
# replace the following line (grab all remote branches)
fetch = +refs/heads/*:refs/remotes/origin/*

# replace with lines listing exactly which branches you want
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/dev_XXX:refs/remotes/origin/dev_XXX

# save the file, now run

git fetch

啊哈!这是我一直在思考的问题 - 是否有办法只克隆一个分支。将其倒置并仅获取所需的内容是一个有趣的想法。但是第一次获取会生成以下错误:“致命:拒绝在非裸存储库的refs/heads/master当前分支中获取”。 - Steve Folly
顺便提一下,使用现代的 Git,您可以使用“git init repoclone”。 - Jakub Narębski
@Steve:啊,你说得对。你可以使用“git fetch origin master; git reset --hard FETCH_HEAD”来设置主分支。 - u0b34a0f6ae
@Jakub:“现代”?甚至1.6.4都不支持。所以更像是最新的git。 - u0b34a0f6ae
从长远来看,为远程添加一个不包含默认通配符的获取配置更容易。然后,您可以像普通克隆一样将本地和远程分支分开,并仅使用简单的 git fetch 进行增量更新。 - CB Bailey
@charles:你是对的,我在看到你的评论的同时也意识到了这一点。 - u0b34a0f6ae

2

另一种方法是避免直接克隆,而是手动添加一个具有自定义获取参考规范集的远程。

例如:

mkdir myclone
cd myclone
git init

git remote add origin url://origin.repo

# Add fetch rules for the branches that we want to track
git config remote.origin.fetch +refs/heads/master:+refs/remotes/origin/master
git config --add remote.origin.fetch +refs/heads/dev_swamy:+refs/remotes/origin/dev_swamy

# fetch now fetches just what we need, subsequently it will do incremental fetches
git fetch

# Creating local branches tracking the remote branches
git checkout -b master origin/master
git branch dev_swamy origin/dev/swamy

1
可能有一种更现代的方法(使用在网上找到的一个小型随机仓库):
干净地检出特定分支,只保留该分支。
$ git clone https://github.com/martinmimigames/little-music-player --single-branch --branch=main 
Cloning into 'little-music-player'...
remote: Enumerating objects: 1187, done.
remote: Counting objects: 100% (292/292), done.
remote: Compressing objects: 100% (142/142), done.
remote: Total 1187 (delta 114), reused 243 (delta 82), pack-reused 895
Receiving objects: 100% (1187/1187), 1.61 MiB | 9.38 MiB/s, done.
Resolving deltas: 100% (487/487), done.

进入结账:

$ cd little-music-player

显示已知的分支(仅确认已知的1个必需分支):

$ git branch --all
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/main

获取另一个分支:

$ git fetch origin m3u:m3u
From https://github.com/martinmimigames/little-music-player
 * [new branch]      m3u        -> m3u

列出已知的分支:
$ git branch --all
  m3u
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/main

为了提高大型仓库的性能,如果您计划在两个分支之间进行一些工作,并且知道它们之间只有最近的偏差(深度值由您决定),则可以向检出添加--depth nnn选项。
如果您只想在存储库中操作特定文件,则使用稀疏检出是另一个选择(在执行获取之前设置更多类似于git init和配置更改的方式-这是一种非常不同的操作方式)。
希望这可以帮助到您。

git fetch origin develop 抛出了这个错误 error: ssh://git-foo/bar/v1/repos/hello-world 未发送所有必要的对象 - undefined

0
我认为这里更重要的问题是其他人会推动什么,而不是你将克隆或拉取什么。由于每个开发者都在自己的分支上工作,另一个问题是如何获得共同的代码库。开发人员是否将他们的分支合并到主分支?然后他们是否将更改后的主分支推送到中央存储库?如果是这样,你无论如何也无法拉取其他开发人员的分支。
如果不是这种情况,我不明白你如何组建一个有效的团队。
最后,我想知道为什么你不想将其他开发人员的分支克隆到你的存储库中?

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