Branches mapping is a set of rules that establish a correspondence between SVN and Git branches and tags. These rules are defined by branches mapping configuration options in SubGit configuration file.
There are few key Subversion concepts, that matter in the context of SubGit mapping process:
A SVN repository can be organized in any way and SubGit can deal with any possible SVN repository layout.
A graphical representation of the explained SVN concepts:
Unlike SVN, which stores data in the form of a filesystem tree, Git represents its data as a set of snapshots of a filesystem, that is being stored in Git's objects database. Due to this difference, most of Git concepts differ from their SVN counterparts albeit have the same names:
A graphical representation of the explained Git concepts:
All the mapping configuration assembled in SubGit configuration file, that is situated in subgit subdirectory inside a newly created Git repository:
GIT_REPOS_PATH/subgit/config |
Here is an example of how the [svn] of the configuration file may look like:
[svn] url = http://svn.example.com/svn/repository_1/project_1 trunk = trunk:refs/heads/master branches = branches/*:refs/heads/project_1/* branches = features_*:refs/heads/features/* tags = tags/*:refs/tags/* shelves = shelves/*:refs/shelves/* excludeBranches = features/feat_4510 excludePath = *.exe |
All the mapping settings reside in [svn] configurations section. There are three main settings groups:
svn.url
This option sets a URL to the SVN project, that is being translated into Git repository. SubGit translates a SVN project into a Git repository: not whole SVN repository to Git repository:
Thus, the `svn.url` setting is supposed to point to your SVN project root, not to SVN repository root; i.e., if you want to mirror, say, 'project1' to Git, then the svn.url must be set as follows:
[svn] url = http://example.com/svn/repository/project1 |
Most of the mapping settings rely on this path and their values are being set relative to this project root.
SubGit support all protocols SVN supports, so the svn.url can be set using the following protocol prefixes:
file://
svn://
svn+ssh://
http://
https://
The next four options – trunk, branches, tags, shelves – actually tell SubGit how SVN to Git entities match to each other. Generic mapping syntax is:
<Mapping-option> = <Subversion-Path-Pattern>:<Git-Reference-Pattern> |
where
svn.trunk
This setting establishes a correspondence between SVN *trunk* and Git branch that represents the main line of development. Assuming, that SVN "main line of development" is being kept in a directory named trunk
and Git master
branch represents the "main line" in Git, the mapping may look like this:
trunk = trunk:refs/heads/master
where
svn.url
i.e. the full path to that directory consists of the URL and this path. Thus, suppose the URL is set like follows:url = http://example.com/svn/repository/project1 |
In this case, the full path to the SVN trunk is equal to:
http://example.com/svn/repository/Project1/trunk |
There are few rules that apply to the svn.trunk
option:
|
svn.branches
This setting establishes a correspondence between SVN and Git branches. Its default value assumes standard SVN layout is used, i.e. that a SVN project branches reside in a directory named branches:
branches = branches/*:refs/heads/*
where
This setting supports wildcards and thus can map a lot of branches at one time. If no wildcards used, the setting represents a path to one particular branch.
Rules that apply to the svn.branches
:
|
Taking the rules into account, the svn.branches
options part in the configuration file may look like following:
branches = branches/*:refs/heads/* branches = feature_*:refs/heads/features/* branches = hotfix/*_*:refs/heads/hotfix/*/* branches = special_branch:refs/heads/special_branch |
svn.tags
This setting establishes a correspondence between SVN and Git tags. The default value assumes standard SVN layout:
tags = tags/*:refs/tags/*
where
SubGit translates SVN tags to Git lightweight tags and any kind of Git tags to SVN.
The svn.tags
option is quite similar to the svn.branches
, it supports both wildcards and direct mapping and the same rules apply to it:
|
As an example, svn.tags
settings may look like this:
tags = 1.0/*:refs/tags/1.0/* tags = 1.5.*:refs/tags/1.5/* tags = tags/2.0.*/*:refs/tags/2.0/*/* tags = tags/special_tag:refs/tags/special_tag |
svn.shelves
Shelves are special entities being introduced by SubGit. SubGit creates shelves when it cannot determine branch name where particular commit belongs to. For example, a shelf will appear in SVN after in the following case:
In such case, SubGit will be able to see all the commits, but won’t be able to recognize the branch name to which they belong. So it will place them into shelves SVN directory.
See a blog post "What are shelves really?" for more details on shelves.
The setting sets a directory in SVN where shelves will be stored:
shelves = shelves/*:refs/shelves/*
where
There are few rules that apply to the svn.shelves
option:
|
svn.excludeBranches, svn.excludeTags
These two settings do reverse job: while all the previous settings tell what to include, these tell SubGit which branches or tags to be excluded from translation. They are interchangeable, any of the two can be used to exclude both *branches* and *tags*.
The settings syntax as simple as:
excludeBranches = SIMPLE_PATTERN
excludeTags = SIMPLE_PATTERN
The SIMPLE_PATTERN
represents a path relative to svn.url
, that leads to a branch or a tag that should be excluded. The path can be direct or it may contain one single wildcard. SubGit appends the SIMPLE_PATTERN
to specified svn.url
and excludes any paths that match the resulting pattern. To illustrate the concept, assume you have the following settings:
[svn] url = http://example.com/svn/repository/project1 … branches = branches/*:refs/heads/* |
You want to import all the branches excluding some "features" branches. In such case, you can exclude them using the following setting:
excludeBranches = branches/feature_* |
assuming that the branches you don't want to include have feature_* name pattern.
In this case, SubGit will exclude any branches or tags that match to the following path:
http://example.com/svn/repository/Project1/branches/feature_* |
svn.excludePath,
svn.includePath
These are settings that provide a possibility to exclude (or vice versa, include) some files from translation. It may be useful e.g. if you have some big files in SVN that you don't want to be present in Git repository. The syntax is simple:
excludePath = PATTERN
includePath = PATTERN
The |
The PATTERN
is an expression that represents files to be excluded or included. Its format is described below:
PATTERN
can be recursive and non-recursive.PATTERN
is treated as recursive if it doesn't contain slashes "/". SubGit will recursively search all specified trunk, branches and tags directories and exclude all files whose names match to the PATTERN
. excludePath = *.html
A PATTERN
is treated as non-recursive if it does contain one or more slashes "/". SubGit will exclude any files in trunk, branches and tags directories, paths to which match to the PATTERN
.
A non-recursive example:
excludePath = */*.html
SubGit will search for *.html files in second level directories within trunk, branches and tags directories, i.e. it will exclude the following files:
http://example.com/svn/project/trunk/*/*.html http://example.com/svn/project/branches/*/*/*.html http://example.com/svn/project/tags/*/*/*.html |
A particular non-recursive PATTERN
case with leading slash "/" represents a particular path to be excluded or included. E.g., if standard SVN project layout is used and svn.url
is set to the following:
http://example.com/svn/project |
And svn.includePath
is set like this:
includePath = /Docs |
Such the setting will include only 'Docs' directory within trunk, branches and tags directories: that means SubGit will translate only paths below:
http://example.com/svn/project/trunk/Docs http://example.com/svn/project/branches/*/Docs http://example.com/svn/project/tags/*/Docs |
Similarly, the following settings will exclude all the *.html files within 'Docs' directory in trunk, branches and tags directories:
excludePath = /Docs/*.html |
That is such setting will exclude the following paths:
http://example.com/svn/project/trunk/Docs/*.html http://example.com/svn/project/branches/*/Docs/*.html http://example.com/svn/project/tags/*/Docs/*.html |
PATTERN
is not allowed.Brackets "[ ]" set a list of possible characters in the PATTERN
:
excludePath = [aoe]*.html |
Such the setting will recursively exclude all the \*.html files which name starts with 'a', 'o' or 'e'.
Spaces within the PATTERN
are allowed:
excludePath = some file name excludePath = some directory/*.exe |
but leading and trailing spaces need to be quoted:
includePath = "filename " includePath = "directory /*.exe" |
otherwise, SubGit will ignore leading/trailing spaces.
Note, that if you have two directories or files at the same SVN file structure level, whose names differ only by leading or trailing spaces - say, "Docs" and "Docs " — that one containing trailing or leading spaces will not be imported/mirrored! |
Two consecutive asterisks "**" in non-recursivePATTERN
mean path of any length.
A PATTERN
with leading asterisks:
excludePath = **/foo/*.exe |
means foo directory with *.exe files anywhere in SVN project. Leading asterisks pattern has some peculiarity: if you have a directory where all the files match given PATTERN
– then not only files will be excluded, the directory itself will not be mirrored/imported as well. Thus, if foo directory contains only *.exe files, then foo will not be imported/mirrored.
Trailing asterisks allows to create non-recursive pattern that will match to directories only, namely:
excludePath = Docs/** |
will exclude Docs directory in trunk, branches and tags root, but won't touch files with the name Docs.
Two consecutive asterisks within path pattern mean a path of any length; that is, setting like:
excludePath = Docs/**/*.exe |
will exclude any *.exe files in Docs directory and all its subdirectories.
When branches, tags or paths are excluded from the translation with the help of one of the above options, modifications to those branches or paths made in Subversion project would not be translated to Git, as well as changes in Git repository made to those locations would not appear in Subversion.
Branches and tags mapping examples