如何将svn分支和标签导入git-svn?

Luí*_*rme 67 svn git git-svn

我有一个我必须承诺的中央SVN存储库,但我对git充满热情(就像我认识的任何其他开发人员一样).这个案子众所周知.

然后我读了一下git-svn并尝试了一下.由于我不需要完整的历史,仅仅两个月左右,我就是这样的:

git svn clone -r 34000 -s https://svn.ourdomain.com/svn/repos/Project/SubProject
Run Code Online (Sandbox Code Playgroud)

像往常一样,SubProject拥有子目录trunk,tagsbranches.大.

然后,为了获得最后一次修订,我做到了

git svn rebase
Run Code Online (Sandbox Code Playgroud)

有些下载,很棒.最后修订,日志等等,好的,现在我将切换到我的功能分支.

$ git branch 
* master
Run Code Online (Sandbox Code Playgroud)
$ git branch -r  
  trunk
Run Code Online (Sandbox Code Playgroud)
$ git branch -a  
* master
  remotes/trunk
Run Code Online (Sandbox Code Playgroud)

问题是:我的分支在哪里?我做错了什么吗?我怎么做才能在新的git仓库中获得我的分支机构?

git-svn,无论我在哪里阅读它,明智地处理分支和标签,但行为不是我所期望的.谢谢!

编辑:我刚刚发现git svn fetch将会这样做.但它会得到所有修改,这是我不喜欢的.

Van*_*uan 75

你需要几个步骤.

  1. 提供正确的trunk,branches和tags文件夹名称并获取svn repo:

    git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo
    git svn fetch
    
    Run Code Online (Sandbox Code Playgroud)
  2. 由于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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 删除标签分支

    git for-each-ref --format="%(refname:short)" refs/remotes/tags | cut -d / -f 2- |
    while read ref
    do 
      echo git branch -rd $ref
    done
    
    Run Code Online (Sandbox Code Playgroud)
  4. 由于上一步中标记的标记指向提交"创建标记",因此我们需要派生"真实"标记,即"创建标记"提交的父级.

    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
    
    Run Code Online (Sandbox Code Playgroud)
  5. 我们现在要做的就是删除旧标签.

  • 第2步:在我的机器上,标签不在`refs/remotes/tags`而不是`refs/remotes/origin/tags`. (7认同)
  • 同样在这里.另请注意,一旦您对其执行的操作感到满意并希望启用实际命令,则需要删除命令中的"echo".我最后得到以下直接标记父级并使用SVN消息的行:`git for-each-ref --format ="%(refname:short)%(objectname)"refs/remotes/tags | cut -d/-f 2- | 而阅读标签参考; do msg = $(git log --pretty = format:'%s'-1 $ {ref}); git tag -f -a $ tag -m"$ msg"$ {ref} ^; done` (6认同)
  • 对于标签迁移,"cut"命令对我来说不起作用,可能是因为"git"命令的输出不同.这个修改过的命令行对我有用:`git for-each-ref --format ="%(refname:short)%(objectname)"refs/remotes/tags | 而阅读标签参考; 做echo git tag -a $ tag -m \"从svn \"$ ref中导入$ tag; done` (3认同)
  • 所以,它不是git输出.因为`echo tags/v0.0.1 | cut -d/-f 2 -`输出`v0.0.1`给我.你能运行这个命令吗? (2认同)

n.r*_*.r. 23

这借鉴了Vanuan的上述答案,但它保留了新标签中原始标签的信息.svngit

$ 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
Run Code Online (Sandbox Code Playgroud)


Moh*_*BIB 12

这是与上面相同nicolai.rostov的答案,但我只是改变我更换了裁判路径refs/remotes/tagsrefs/remotes/origin/tags 我使用Git版本2.1.1cygwin终端.

$ 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
Run Code Online (Sandbox Code Playgroud)

  • 我发现这将标签名称创建为“tag/<标签名称>” - 我希望标签名称只是名称(主要是因为强迫症,以匹配 gitkraken 显示的内容!),所以我将其更改为 `TAG_NAME= ${分支#*/*/}` (2认同)

rmk*_*rmk 9

你说你的收银台里没有你的分店.

这可能是你的svn repo布局的问题.

'标准布局'是:

branches/

tags/

trunk/

如果您的布局如下:

branches/user1/

branches/user2/

然后,当你执行git svn fetch/clone时,你将失去你的分支.

要解决这个问题,你应该给出论证

--branches=branches/*/* 来git克隆.


car*_*ira 6

我编写了一个脚本来帮助您根据需要进行迁移。该脚本并不完美,但我希望这可以帮助您:

更多信息可以访问: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("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2"@"$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("^ ", "", $1); sub(" $", "", $1); print $1}' )

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.'
Run Code Online (Sandbox Code Playgroud)


Von*_*onC 5

如果你想在从svn导入后执行git分支时看到你的分支,你应该使用ruby脚本svn2git(和git2svn)

它比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
Run Code Online (Sandbox Code Playgroud)

git-svn将通过提交历史记录来构建一个新的git repo.
它将所有分支和标签导入为远程SVN分支,而您真正想要的是git-native本地分支和git标记对象.因此,在导入此项目后,您将获得:

  $ 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 ]
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)