我该如何在裸仓库之间同步Git分支?

5

我有一个裸库,其origin在远程机器上。

我想将其分支下载到本地裸库。也就是说,我希望在分支列表中使用git branch -vva命令查看它们,如下所示:

* master                0bc84f0 [origin/master] something...
  remotes/origin/HEAD   -> origin/master
  remotes/origin/master 0bc84f0 something...

在非裸库的情况下,git pull --all 命令可以同步分支(将远程分支显示在本地库中),但是对于裸库而言,pull 命令则不可行。
在这种情况下,如何同步远程分支呢?
注意:git --fetch 命令无效,在使用该命令后,远程分支仍然不可见。
$ git remote -v
origin  git://host/project.git (fetch)
origin  git://host/project.git (push)
$ git branch -vva
* master 4085a31 ...something
$ git fetch
From git://host/project.git
 * branch            HEAD       -> FETCH_HEAD
$ git branch -vva
* master 4085a31 ...something

附加信息:我的config如下:

[core]
        repositoryformatversion = 0
        filemode = false
        bare = true
        symlinks = false
        ignorecase = true
[remote "origin"]
        url = git://host/project.git

我在一个新克隆的(也是裸)仓库中的config

[core]
        repositoryformatversion = 0
        filemode = true
        bare = true
[remote "origin"]
        url = git://host/project.git

@Yaba的评论解决了问题。6小时后他将获得奖励。另外一个问题:这是一个git的bug还是一个非常规特性? - peterh
请看我的编辑(以解决副问题)。 - VonC
5个回答

10

解决方案1:

您需要将您的存储库转换为镜像存储库:

git remote add --mirror=fetch origin <url>
git fetch

一个镜像仓库会在拉取(fetch)后将本地引用与原始引用同步。它的缺点是,镜像应该是远程仓库的精确副本,而这可能不是你的目标。

解决方案 #2:

(利用评论的 @peterh 扩展):

在 git 配置中(裸仓库的情况下,简单地说就是 repo/config),一个

[remote "origin"]
  fetch = +refs/heads/*:refs/remotes/origin/*

应该存在。如果不存在,则可能是一个非常规的git功能或者是git的错误。您可以手动修复它。之后,git fetch 将会生效。


我不知道这是一件事情。非常棒! - alexbclay
谢谢你的回答!但是,目前我不会将我的存储库转换为镜像存储库。 - peterh
1
问题在于:mirror-repo是远程端的完全复制,这不是我的意图。我只想看到远程分支。 - peterh
你的配置文件中是否有以下条目:[remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/*? 这表示获取所有分支并将它们写入到 refs/remotes/origin。 - yaba
@yaba 将此插入配置文件后,“git fetch”可以工作,但我怀疑现在是一个 git 的 bug。 - peterh
显示剩余2条评论

5

执行 git fetch 应该足够了。

只是为了测试,试着再次将裸仓库克隆到新的本地仓库中。然后看看远程跟踪分支是否已经存在。

git clone git://host/project.git newproject
cd newproject
git branch -avv

我已经进行了新的克隆,但仍然无法看到任何远程分支,尽管原始指向了正确的URL。
情况仍然是一样的,正如您在我的问题结尾处所看到的(正确的原始URL,但仍然没有远程分支)。这意味着这些远程分支首先不在远程存储库中。
克隆的默认获取refspec是:
fetch = +refs/heads/*:refs/remotes/origin/*

如果远程仓库有其他分支,它们也会被克隆。
如果git config -l命令没有显示任何fetch键,请尝试添加一个:
git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/*

请使用以下方法检查:

git config --get remote.origin.fetch

请参见“git fetch doesn't fetch all branches”。


真正的问题是:什么在OP的配置中使得git clone只克隆master并没有包含任何fetch refspec?

可能设置了Git环境变量
例如,GIT_TEMPLATE_DIR(其中包括默认配置)

仅添加fetch refspec不能解决实际问题。
为了解决实际问题,需要更多信息(Git版本、操作系统版本等)。


正如您在问题末尾所看到的,git fetch无法工作。我已将命令及其输出复制到问题中。两个存储库都是裸存储库。 - peterh
@peterh 是的,所以我建议使用 git clone(进行测试),而不是 git fetch - VonC
好的,明白!我已经克隆了一个新的副本,尽管origin指向正确的URL,但仍然看不到任何远程分支。情况还是一样的,你可以在我的问题末尾看到(origin URL 正确,但仍然没有远程分支)。 - peterh
@peterh 这意味着那些远程分支本来就不在远程仓库中。克隆的默认refspec(https://git-scm.com/book/en/v2/Git-Internals-The-Refspec)是`fetch = +refs/heads/*:refs/remotes/origin/*`:如果远程仓库有其他分支,它们也会被克隆。 - VonC
@peterh 我已经编辑了答案:你可以尝试在你的 remote.origin 键中添加一个 fetch 条目吗? - VonC
@peterh,只是为了明确起见,我建议在看到您的config -l之后添加git fetch refspec:我已经添加了命令以添加fetch部分。 - VonC

2

在裸仓库中的配置中添加以下行:

fetch = +refs/*:refs/*

您的配置将如下所示:

[core]
    repositoryformatversion = 0
    filemode = false
    bare = true
    symlinks = false
    ignorecase = true
[remote "origin"]
    url = git://host/project.git
    fetch = +refs/*:refs/*

然后在你的代码库中执行以下操作:

git --bare  fetch

新的分支将被下载


1

git pull 是运行 git fetch 同步分支的简写形式,然后使用 git merge 将本地副本与远程版本合并。

从您的裸仓库中,您只需要运行 git fetch 来同步您的本地分支引用。

有关更多信息,请参见此处: https://git-scm.com/docs/git-fetch


git --fetch 不起作用。我更新了问题。据我理解文档(非常感谢链接),它只会加载指定的远程分支,而不是远程分支列表。 - peterh
当我设置一个裸库,然后将其指向一个完整的库并执行 git fetch 时,它会更新我的裸库的远程分支列表,并显示如下内容:* [new branch] adfsl -> origin/adfsl 或者 38b8475..9bd1033 adff -> origin/adff。你能否发布一下在执行 fetch 前后看到的内容? - alexbclay
是的,我将整个场景复制粘贴到了我的问题中。 - peterh

1

需要从以下内容开始:

git clone --mirror git@host/project.git

这将创建一个裸仓库,并准备接收更新。 然后进入您的project.git并更新本地裸仓库:

git --bare  fetch

刚刚测试过了,运行得很好。

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