Gitea: Migrating from SVN to Git

Table of contents

environmental information

migration steps


Both SVN and Git are excellent version management tools. Unfortunately, there are quite a few articles on the web that are misleading about the process, commands, and instructions for migrating from SVN to Git. Therefore, this article takes Gitea as an example to demonstrate the detailed process of migrating from SVN to Git.

Prerequisites for this article:

  • Gitea installation has been completed (including Git software installation)
  • In Gitea, the initial configuration is done and running
  • In Gitea, configure Organization, Teams, User Accounts and other organizational collaboration information as needed (optional)
  • In Gitea, the Repository has been created (here the name is: gsyspm , no need to initialize the Repository)

environmental information

When the above git repository is created and not initialized, it needs to be migrated from the original SVN repository to Git, including the commit and author log in SVN. SVN information that needs to be exported:

  • SVN仓根URL:http://20.1.1.11:7001/usvn/svn/sys_pm
  • The path of the trunk in the SVN warehouse relative to the root: pmis/01develop/02code/trunk
  • The path of branches in the SVN warehouse relative to the root: pmis/01develop/02code/branches
  • There is no Tags information in the SVN repository
  • The range of SVN version numbers that need to be migrated: from 1 to HEAD

migration steps

The following steps complete the migration from SVN to Git through the git svn command:

1. Create a temporary directory for migration on any PC (with access to SVN and Gitea): migrate_svn_to_git/

2. Enter the directory. Create the text authors_map.txt to store the SVN author to Git author mapping information file, the format is as follows:

loginname=JoeUser<[email protected]>

     

Alternatively, the author mapping file can be automatically generated in the following way.

   Enter the existing local SVN directory (the directory has been checked out from SVN to the latest) and generate (execute in Bash) the authors_map.txt file through the following command, and then copy the generated txt file to the migrate_svn_to_git/  directory  :

svn log -r 1:HEAD --xml | grep "<author" | sort -u | awk -F '<author>' '{print $2}' | awk -F '</author>' '{print $1"="$1"<"$1"@yykj.com>" }'  > authors_map.txt


3. Export from the SVN warehouse to the local through the following two git svn commands (executed in Bash):

#以SVN仓根URL对当前本地目录进行git初始化
git svn init http://20.1.1.11:7001/usvn/svn/sys_pm --prefix fromsvn/ --no-metadata --username=LOGIN_SVNUSER  --trunk=pmis/01develop/02code/trunk --branches=pmis/01develop/02code/branches 



#从SVN仓导出到本地git仓中(耗时可能很长甚至几天几夜)
git svn fetch  -r 1:HEAD --authors-file=authors_map.txt

Option description:

  • --prefix   specifies the prefix value in "refs/remotes/$prefix/" in the ".git/" and ".git/svn/" directories (there is a slash at the end of the value), if not specified, the default is "origin /" (approximately understood as the alias of the remote SVN warehouse, the reason why it is called approximate is that it is not a standard git remote warehouse concept, and this alias cannot be displayed through the git remote command)
  • --no-metadata   does not export SVN metadata information (the .svn directory will not be generated locally when exporting). If you need to reverse import from git to git and export SVN metadata information, you cannot use this option
  • --username   specifies the login SVN username. If not specified, the current login operating system user will be used as the default SVN login name
  • --trunk --branches --tags   The standard structure of SVN is the trunk/branch/Tags directory name is "trunk/branches/tags" and they are directly in the root directory of the SVN warehouse. For the standard organization, the option should be changed to - -stdlayout (or -s). Since the SVN here is not a standard SVN structure (the trunk branch directory name conforms to the standard, but it is not directly placed in the root directory of the SVN warehouse), so specify its relative path relative to the root directory of the SVN warehouse through --trunk and --branches respectively
  • -r  specifies the starting and ending range of the exported SVN version number
  • --authors-file   specifies the mapping file from SVN authors to git authors. If the range of commit authors existing in SVN exceeds the range of the mapping file, an error will be reported and aborted

4. After the export, the tags and branch information are in the .git/svn/ directory. You need to create git local tags and branches based on this, and then push them to the remote end of gitea in the following steps. That is, there are three types of refs information for tags and branches:

  • Remote refs information of SVN (after exporting, store in the .git/svn/refs/remotes directory)
  • The refs information of the git local warehouse (stored in the .git/refs directory)
  • git's remote refs information (stored in the .git/refs/remotes directory)

Use the following command to convert "remote refs information of SVN" to "refs information of git local warehouse", and then clean and delete "remote refs information of SVN": (executed in Bash)

#先for循环调整tags(其中“fromsvn”为前文指定的--prefix)
for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/fromsvn/tags);
do
    tagname=${t/fromsvn\/tags\//}
    git tag ${tagname} $t && git branch -D -r $t;
done;

[Note] refs are pointers inside git, pointing to the 40-byte SHA-1 hash value. In the command, refs/remotes is the head pointer pointing to each remote branch, and refs/tags is a list of local tags.

Command description:

  • The git for-each-ref   git command lists git internal refs (including those in the ".git/" and ".git/svn/" directories) that match the specified pattern and outputs them in the specified format. For Tag output format: refs/remotes/ fromsvn /tags/XXX (where fromsvn is the --prefix specified above). You can view the contents of the .git/config file generated by the git svn initialization command, and find out that the SVN Tag is mapped to the name of the git local refs.
  • ${ t / fromsvn\/tags\/ /}   Bash syntax. The structure is ${ VAR / PATTERN /NEWSTRING}, and the variable value is matched regularly and replaced. The meaning here is to delete the "fromsvn/tags/" string in the variable value.
  • git tag <tagname> <object>   creates a tag locally in git. tagname is a regularized string; if no <object> is specified, the tag will be created with the current HEAD version number by default. The default value is not used here, and it is specified by <object> as: the Hash value of the refs
  • git branch-D -r   delete remote refs information
#然后再for循环调整branch(其中“fromsvn”为前文指定的--prefix)
for b in $(git for-each-ref --format='%(refname:short)' refs/remotes/fromsvn);
do
    branchname=${b/fromsvn\//}
    git branch ${branchname,,} refs/remotes/$b && git branch -D -r $b;
done;

Command description: 

  • The git for-each-ref   git command lists git internal refs (including those in the ".git/" and ".git/svn/" directories) that match the specified pattern and outputs them in the specified format. For the branch output form: refs/remotes/ fromsvn /XXX (where fromsvn is the --prefix specified above). You can view the contents of the .git/config file generated by the git svn initialization command, and find out that the SVN branch is mapped to the git local refs name.
  • ${ branchname,, }   Bash syntax. The structure is ${ VAR ,,}, which means converting all variable values ​​to lowercase.
  • git branch <branchname> <start-point>   creates a branch locally in git. If no <start-point> is specified, Branch will be created with the current HEAD version number by default. The default value is not used here, and specified by <start-point> as: the Hash value of the refs
  • git branch-D -r   delete remote refs information

5. Convert the ignore file (choose whether to execute it according to actual needs, not executed here)

git svn show-ignore > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore'


6. Other adjustments. After the above processing is completed, you should check whether the branch and tag items are correct. If you need to rename or delete branches/tags that are not used in history, you can manually execute the git command.

7. View and check the result (executed in Bash)
8. So far, the local migration from SVN to git has been completed.

git branch
git log
git tag

9. In the next step, push from git local to gitea remote warehouse (executed in Bash):

#增加git远端仓定义
git remote add origin_base http://20.200.54.51:3000/gsyspm/base_repos.git


#将本地仓所有分支推送至远端仓(若弹出输入用户密码,请输入gitea_admin用户和密码)
git push --all origin_base


#将本地仓所有tag信息推送至远端仓(若弹出输入用户密码,请输入gitea_admin用户和密码)
git push --tags origin_base

Option description:

  • --all   Push all local branches to the remote warehouse (without pushing tag information).
  • --tags   The --tag option in git push means to push all the tag information of the local warehouse to the remote warehouse (do not push the branch branch).

10. View the results of the gitea server through the browser.

Guess you like

Origin blog.csdn.net/zyplanke/article/details/124468631