11

我有一个从 svn 存储库创建的本地 git 存储库:

$ git svn clone -s svn:...

然后我创建了一个备份遥控器并将所有内容推送到它:

$ git remote add backup git@myhost:mybackup.git
$ git push --mirror backup

现在,当我尝试从备份中克隆时,它丢失了所有 svn 标签和分支。

$ git clone git@myhost:mybackup.git
$ cd mybackup
$ git branch -a
* master
  origin
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

如何克隆带有所有标签和分支的 repo?

我发现的唯一方法是镜像回购:

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

这将创建一个本地mybackup.git目录,该目录知道所有标签/分支(我可以使用制表符完成来获取整个列表),但它不是一个有效的可用存储库:

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

必须有命令行选项才能真正克隆带有所有分支/标签的仓库???

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

4

2 回答 2

10

有两种方法可以改进你的命令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 创建一个裸存储库而不是工作存储库,因此您需要将其转换为工作存储库。

于 2016-03-17T15:30:39.507 回答
6

经过大量搜索,我终于找到了答案......

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

现在 agit branch -a显示了我所有的远程分支。

我不确定git init这里是否需要它,或者是否仅在git init --bare变体中需要它(请参阅下面的 shell 脚本中注释掉的行),但我确信如果不需要它,将它留在里面没有任何害处。

我这样做的主要原因是复制我的 SVN 标签/分支,而不是仅仅master指向 SVNtrunk而不必解析整个 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
于 2013-08-30T20:27:24.857 回答