如何将 svn 分支和标签导入 git-svn?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2244252/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to import svn branches and tags into git-svn?
提问by Luís Guilherme
I have got a central SVN repository I must commit to, but I've got a passion for git (like any other developer I know). The case is well known.
我有一个必须提交的中央 SVN 存储库,但我对 git 充满热情(就像我认识的任何其他开发人员一样)。这个案子是众所周知的。
Then I read about git-svn and gave it a try. Since I don't need the full history, just from two months or so, I did like this:
然后我阅读了 git-svn 并尝试了一下。由于我不需要完整的历史记录,只需两个月左右,我就这样做了:
git svn clone -r 34000 -s https://svn.ourdomain.com/svn/repos/Project/SubProject
SubProject had, as usual, the subdirectories trunk
, tags
and branches
. Great.
像往常一样,SubProject 有子目录trunk
,tags
和branches
. 伟大的。
Then, in order to get the last revision, I did
然后,为了得到最后的修订,我做了
git svn rebase
Some downloads later, great. Last revision, logs, etc. Ok, now I'll switch to my feature branch.
后来下载了一些,很好。上次修订、日志等。好的,现在我将切换到我的功能分支。
$ git branch
* master
$ git branch -r
trunk
$ git branch -a
* master
remotes/trunk
The questions are: Where are my branches? Have I done something wrong? How should I do in order to get my branches in the new git repo?
问题是:我的分支机构在哪里?我做错了什么吗?我应该怎么做才能在新的 git repo 中获取我的分支?
git-svn, wherever I have read about it, dealt wisely with branches and tags, but the behaviour is not what I expected. Thanks!
git-svn,无论我在哪里读到过它,都明智地处理了分支和标签,但行为并不是我所期望的。谢谢!
EDIT: I have just found out that git svn fetch
will do it. But it will get all revisions, which is something I wouldn't like.
编辑:我刚刚发现git svn fetch
可以做到。但它会得到所有的修改,这是我不喜欢的。
回答by Vanuan
You'll need several steps.
你需要几个步骤。
supply proper trunk, branches and tags folder names and fetch svn repo:
git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo git svn fetch
Since tags in svn are real branches, create git tags from tag branches:
git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags | cut -d / -f 3- | while read ref do echo git tag -a $ref -m 'import tag from svn' done
Delete tag branches
git for-each-ref --format="%(refname:short)" refs/remotes/tags | cut -d / -f 2- | while read ref do echo git branch -rd $ref done
Since tags marked in the previous step point to a commit "create tag", we need to derive "real" tags, i.e. parents of "create tag" commits.
git for-each-ref --format="%(refname:short)" refs/tags | while read ref do tag=`echo $ref | sed 's/_/./g'` # give tags a new name echo $ref -\> $tag git tag -a $tag `git rev-list -2 $ref | tail -1` -m "proper svn tag" done
All we have to do now is to remove old tags.
提供正确的主干、分支和标签文件夹名称并获取 svn repo:
git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo git svn fetch
由于 svn 中的标签是真正的分支,因此从标签分支创建 git 标签:
git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags | cut -d / -f 3- | while read ref do echo git tag -a $ref -m 'import tag from svn' done
删除标签分支
git for-each-ref --format="%(refname:short)" refs/remotes/tags | cut -d / -f 2- | while read ref do echo git branch -rd $ref done
由于在上一步中标记的标签指向提交“创建标签”,我们需要派生“真实”标签,即“创建标签”提交的父项。
git for-each-ref --format="%(refname:short)" refs/tags | while read ref do tag=`echo $ref | sed 's/_/./g'` # give tags a new name echo $ref -\> $tag git tag -a $tag `git rev-list -2 $ref | tail -1` -m "proper svn tag" done
我们现在要做的就是删除旧标签。
回答by n.r.
This draws on Vanuan's answer above, but it preserves the messageof the original svn
tag in the new git
tag.
这借鉴了上面 Vanuan 的回答,但它在新标签中保留了原始标签的消息。svn
git
$ git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags \
| while read BRANCH REF
do
TAG_NAME=${BRANCH#*/}
BODY="$(git log -1 --format=format:%B $REF)"
echo "ref=$REF parent=$(git rev-parse $REF^) tagname=$TAG_NAME body=$BODY" >&2
git tag -a -m "$BODY" $TAG_NAME $REF^ &&\
git branch -r -d $BRANCH
done
回答by Mohamed EL HABIB
This is the same as nicolai.rostov's answer above, but i just change the refs path
I replaced refs/remotes/tags
by refs/remotes/origin/tags
I'm using git version 2.1.1
into cygwin
terminal.
这与上面 nicolai.rostov 的回答相同,但我只是更改了我替换的 refs 路径refs/remotes/tags
,refs/remotes/origin/tags
我正在使用 git 版本2.1.1
进入cygwin
终端。
$ git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/origin/tags \
| while read BRANCH REF
do
TAG_NAME=${BRANCH#*/}
BODY="$(git log -1 --format=format:%B $REF)"
echo "ref=$REF parent=$(git rev-parse $REF^) tagname=$TAG_NAME body=$BODY" >&2
git tag -a -m "$BODY" $TAG_NAME $REF^ &&\
git branch -r -d $BRANCH
done
回答by rmk
You say that you haven't gotten your branches in your checkout.
你说你在结账时没有得到你的分支机构。
This is likely a problem with the layout of your svn repo.
这可能是 svn 存储库布局的问题。
The 'standard layout' is:
“标准布局”是:
branches/
branches/
tags/
tags/
trunk/
trunk/
If you have your layout like this:
如果你有这样的布局:
branches/user1/
branches/user1/
branches/user2/
branches/user2/
Then, you will lose your branches when you do git svn fetch / clone.
然后,当您执行 git svn fetch / clone 时,您将丢失分支。
To fix this, you should give the argument
要解决这个问题,你应该给出论点
--branches=branches/*/*
to git clone.
--branches=branches/*/*
git克隆。
回答by VonC
If you want to see your branches when doing a git branch after a import from svn, you should use the ruby script svn2git (and git2svn)
如果您想在从 svn 导入后执行 git 分支时查看您的分支,您应该使用 ruby 脚本svn2git(和 git2svn)
It is better than git svn clone because if you have this code in svn:
它比 git svn clone 更好,因为如果你在 svn 中有这个代码:
trunk
...
branches
1.x
2.x
tags
1.0.0
1.0.1
1.0.2
1.1.0
2.0.0
git-svn
will go through the commit history to build a new git repo.
It will import all branches and tags as remote SVN branches, whereas what you really want is git-native local branches and git tag objects. So after importing this project, you would get:
git-svn
将通过提交历史来构建一个新的 git repo。
它会将所有分支和标签作为远程 SVN 分支导入,而您真正想要的是 git-native 本地分支和 git tag 对象。所以导入这个项目后,你会得到:
$ git branch
* master
$ git branch -a
* master
1.x
2.x
tags/1.0.0
tags/1.0.1
tags/1.0.2
tags/1.1.0
tags/2.0.0
trunk
$ git tag -l
[ empty ]
After svn2git
is done with your project, you'll get this instead:
后svn2git
与您的项目完成后,你会得到这个:
$ git branch
* master
1.x
2.x
$ git tag -l
1.0.0
1.0.1
1.0.2
1.1.0
2.0.0
回答by carolnogueira
I wrote a script to help migrate as you want. The script is not perfect, but I hope this could help you:
我编写了一个脚本来帮助您根据需要进行迁移。该脚本并不完美,但我希望这可以帮助您:
For more information, you can visit: https://github.com/MPDFT/svn-to-git
更多信息可以访问:https: //github.com/MPDFT/svn-to-git
#!/bin/bash
####### Project name
PROJECT_NAME="myproject"
EMAIL="mycompany.com"
###########################
####### SVN
# SVN repository to be migrated
BASE_SVN="http://svn.mycompany.com/svn/repo/sistemas/myproject"
# Organization inside BASE_SVN
BRANCHES="branches"
TAGS="tags"
TRUNK="trunk"
###########################
####### GIT
# Git repository to migrate
GIT_URL="https://git.mycompany.com/git/repo/sistemas/myproject.git"
###########################
#### Don't need to change from here
###########################
# Geral Configuration
ABSOLUTE_PATH=$(pwd)
TMP=$ABSOLUTE_PATH/"migration-"$PROJECT_NAME
# Branchs Configuration
SVN_BRANCHES=$BASE_SVN/$BRANCHES
SVN_TAGS=$BASE_SVN/$TAGS
SVN_TRUNK=$BASE_SVN/$TRUNK
AUTHORS=$PROJECT_NAME"-authors.txt"
echo '[LOG] Starting migration of '$SVN_TRUNK
echo '[LOG] Using: '$(git --version)
echo '[LOG] Using: '$(svn --version | grep svn,)
mkdir $TMP
cd $TMP
echo
echo '[LOG] Getting authors'
svn log -q $BASE_SVN | awk -F '|' '/^r/ {sub("^ ", "", ); sub(" $", "", ); print " = "" <""@"$EMAIL">"}' | sort -u >> $AUTHORS
echo
echo '[RUN] git svn clone --authors-file='$AUTHORS' --trunk='$TRUNK' --branches='$BRANCHES' --tags='$TAGS $BASE_SVN $TMP
git svn clone --authors-file=$AUTHORS --trunk=$TRUNK --branches=$BRANCHES --tags=$TAGS $BASE_SVN $TMP
echo
echo '[LOG] Getting first revision'
FIRST_REVISION=$( svn log -r 1:HEAD --limit 1 $BASE_SVN | awk -F '|' '/^r/ {sub("^ ", "", ); sub(" $", "", ); print }' )
echo
echo '[RUN] git svn fetch -'$FIRST_REVISION':HEAD'
git svn fetch -$FIRST_REVISION:HEAD
echo
echo '[RUN] git remote add origin '$GIT_URL
git remote add origin $GIT_URL
echo
echo '[RUN] svn ls '$SVN_BRANCHES
for BRANCH in $(svn ls $SVN_BRANCHES); do
echo git branch ${BRANCH%/} remotes/svn/${BRANCH%/}
git branch ${BRANCH%/} remotes/svn/${BRANCH%/}
done
git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/origin/tags | grep -v "@" | cut -d / -f 3- |
while read ref
do
echo git tag -a $ref -m 'import tag from svn'
git tag -a $ref -m 'import tag from svn'
done
git for-each-ref --format="%(refname:short)" refs/remotes/origin/tags | cut -d / -f 1- |
while read ref
do
git branch -rd $ref
done
echo
echo '[RUN] git push'
git push origin --all --force
git push origin --tags
echo 'Sucessufull.'
回答by Qianlong
For those who have to work on Windws at work, here is a solution up-to-date with git version 2.17.0 (and theoretically also works for versions before)
对于那些必须在工作中使用 Windws 的人,这里有一个最新的 git 版本 2.17.0 解决方案(理论上也适用于之前的版本)
git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo
git svn fetch
for /f "tokens=1-2 delims= " %a in ('git for-each-ref --format="%(refname:lstrip=-1) %(objectname)" refs/remotes/origin/tags') do git tag -a %a %b -m "import tag from svn"
回答by cweiske
I had the same problem - tags and branches were missing when I specified the revision:
我遇到了同样的问题 - 指定修订版时缺少标签和分支:
$ git svn clone -r 34000 -s https://...
The fix was to specifiy a range of revisions, -r 34000:HEAD
:
修复是指定一系列修订,-r 34000:HEAD
:
$ git svn clone -r 34000:HEAD -s https://...