如何克隆一个包含所有分支和标签的 git 仓库,从 refs/remotes 目录下进行克隆?

11

我有一个本地的Git仓库,是从一个SVN仓库创建的:

$ git svn clone -s svn:...

然后我创建了一个备份远程,并将所有东西推送到它上面:

$ git remote add backup git@myhost:mybackup.git
$ git push --mirror backup
现在,当我尝试从备份进行克隆时,它缺少所有svn标签和分支。
现在,当我尝试从备份进行克隆时,它缺少所有svn标签和分支。
$ git clone git@myhost:mybackup.git
$ cd mybackup
$ git branch -a
* master
  origin
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

如何克隆包含所有标签和分支的代码库?

我发现唯一的方法是镜像这个代码库:

$ git clone --mirror git@myhost:mybackup.git

这将创建一个本地的mybackup.git目录,其中包含所有标签/分支的信息(我可以使用制表符自动补全获取整个列表),但它不是一个有效的可用于操作的仓库:

$ git checkout mytag
fatal: This operation must be run in a work tree

必须有命令行选项才能真正克隆具有所有分支/标记的存储库吗?

我在这里找到了几个相关的问题,但是没有一个答案适用于这种情况。我认为区别在于我的克隆是使用--mirror创建的?


更多信息:我可以看到,我的新克隆知道的分支位于我的备份的refs/heads目录中,而我找不到的分支位于refs/remotes中(奇怪的是,backup也在refs/remotes中 - 这是--mirror的副作用)。 - Shadow Man
2个回答

11

有两种方法可以提高您的命令行技能:git clone --mirror git@myhost:mybackup.git 我发现的是这种方法,假设您的命令已经创建了一个名为 mybackup.git 的目录:

有两种方法可提高命令行技巧:git clone --mirror git@myhost:mybackup.git 我发现的是,如果您的命令已经创建了名为mybackup.git的目录,则使用此方法:

mkdir mybackup
mv mybackup.git mybackup/.git
cd mybackup
git init

现在,您拥有一个完整的工作目录。

或者您也可以在这个页面上阅读:https://git.wiki.kernel.org/index.php/Git_FAQ#How_do_I_clone_a_repository_with_all_remotely_tracked_branches.3F

git clone --mirror git@myhost:mybackup.git mybackup/.git
cd mybackup
git config --bool core.bare false

我认为除了最后一行之外,两者是等价的,而且git config --bool core.bare false命令比执行git init更加简洁。

总之,--mirror创建的是裸仓库而不是工作仓库,因此你需要将其转换为工作仓库。


1
谢谢。由于这个方案似乎可行且更简单,我将退役我的解决方案。然后,您只需要将SVN连接到新的存储库即可完成。 - Shadow Man

6

经过长时间的搜索,我终于找到了答案...

git clone git@myhost:mybackup.git newdirectory
cd newdirectory
git fetch origin refs/remotes/*:refs/remotes/*
git init

现在,git branch -a会显示我所有的远程分支。
我不确定是否需要使用git init,或者它是否仅在git init --bare变体中需要(请参见下面shell脚本中的注释行),但我确定如果不需要,将其保留不会有任何损害。
我的主要目的是复制我的SVN标签/分支,而不仅仅是让master指向SVN trunk,也不需要解析整个SVN历史记录(对于具有大量历史记录、标签和分支的项目来说非常缓慢)。因此,要复制我的SVN信息:
git svn init -s "svn://mysvnhost/mysvnrepo/myproject"
git svn fetch
git checkout master

为了加快这个过程,我创建了一个shell脚本:
#!/bin/sh
#
# git-clone-svn-based-repo.sh:
#
# clones a git-svn based repo including all SVN commits without pounding
# the SVN server for hours (just a quick refresh taking seconds)
#

usage_exit ()
{
   echo "Usage: $0 <git-repo> <dest-directory> <svn-project>"
   exit 1
}


if ! git ls-remote "$1" > /dev/null  2>&1
then
   echo "No git repo found at: $1"
   usage_exit
fi

if [ -r "$2" ]
then
   echo "File or directory already exists: $2"
   usage_exit
fi

if ! svn ls "$3" 2> /dev/null | grep -q trunk
then
   echo "No SVN project found at: $3"
   usage_exit
fi

# create new bare git repo
mkdir "$2"
cd "$2"
git init --bare .git

# fetch everything from backup
git remote add backup "$1"
git fetch backup refs/remotes/*:refs/remotes/*
git fetch backup refs/heads/*:refs/heads/*
git fetch backup refs/tags/*:refs/tags/*

# disable future fetching from backup
# setup to push all remote refs to backup by default
git config remote.backup.fetch do_not_fetch_from_backup
git config remote.backup.push '+refs/remotes/*:refs/remotes/*'

# initialize git repo to usable (non-bare) state
git init

# update SVN references
git svn init -s "svn://svn.crc-corp.com/carsrepository/$3"
git config svn.authorsfile $HOME/projects/authors.txt
git svn fetch

# update master to current SVN trunk
git checkout master
git svn rebase
# update ignore properties from SVN
git svn show-ignore >> .git/info/exclude

为了从一个已存在的git SVN仓库创建备份,请按照以下步骤操作:
# create a bare backup repo at git@myhost:mybackup.git
git remote add backup git@myhost:mybackup.git
git config remote.backup.fetch do_not_fetch_from_backup
git config remote.backup.push '+refs/remotes/*:refs/remotes/*'
git push backup

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