Create a users file (i.e. users.txt
) for mapping SVN users to Git:
user1 = First Last Name <email@address.com>
user2 = First Last Name <email@address.com>
...
You can use this one-liner to build a template from your existing SVN repository:
svn log -q | awk -F '|' '/^r/ {gsub(/ /, "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt
SVN will stop if it finds a missing SVN user, not in the file. But after that, you can update the file and pick up where you left off.
Now pull the SVN data from the repository:
git svn clone --stdlayout --no-metadata --authors-file=users.txt svn://hostname/path dest_dir-tmp
This command will create a new Git repository in dest_dir-tmp
and start pulling the SVN repository. Note that the "--stdlayout" flag implies you have the common "trunk/, branches/, tags/" SVN layout. If your layout differs, become familiar with --tags
, --branches
, --trunk
options (in general git svn help
).
All common protocols are allowed: svn://
, http://
, https://
. The URL should target the base repository, something like http://svn.mycompany.com/myrepo/repository. The URL string must not include /trunk
, /tag
or /branches
.
Note that after executing this command it very often looks like the operation is "hanging/frozen", and it's quite normal that it can be stuck for a long time after initializing the new repository. Eventually, you will then see log messages which indicate that it's migrating.
Also note that if you omit the --no-metadata
flag, Git will append information about the corresponding SVN revision to the commit message (i.e. git-svn-id: svn://svn.mycompany.com/myrepo/<branchname/trunk>@<RevisionNumber> <Repository UUID>
)
If a user name is not found, update your users.txt
file then:
cd dest_dir-tmp
git svn fetch
You might have to repeat that last command several times, if you have a large project until all of the Subversion commits have been fetched:
git svn fetch
When completed, Git will checkout the SVN trunk
into a new branch. Any other branches are set up as remotes. You can view the other SVN branches with:
git branch -r
If you want to keep other remote branches in your repository, you want to create a local branch for each one manually. (Skip trunk/master.) If you don't do this, the branches won't get cloned in the final step.
git checkout -b local_branch remote_branch
# It's OK if local_branch and remote_branch are the same names
Tags are imported as branches. You have to create a local branch, make a tag and delete the branch to have them as tags in Git. To do it with tag "v1":
git checkout -b tag_v1 remotes/tags/v1
git checkout master
git tag v1 tag_v1
git branch -D tag_v1
Clone your GIT-SVN repository into a clean Git repository:
git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir
The local branches that you created earlier from remote branches will only have been copied as remote branches into the newly cloned repository. (Skip trunk/master.) For each branch you want to keep:
git checkout -b local_branch origin/remote_branch
Finally, remove the remote from your clean Git repository that points to the now-deleted temporary repository:
git remote rm origin
Best Answer
There are two ways with subversion, one is specific to the user and the other is actually maintained in the repository, and therefore affects everyone.
For a list of globally ignored files (exclusive to each user/machine), you need to edit the subversion config file and alter the global-ignores directive in the miscellany section. The config file is documented and the syntax is very simple. For example:
On a UNIX system, the config file is found at
~/.subversion/config
. On a Windows system, the config file is found at%APPDATA%\Subversion\config
or in the registry underHKCU\Software\Tigris.org\Subversion\Config
.Once you set this up, you will never accidently add these files to your repository, nor will the files show up as ? in your
svn stat
commands. If your repository already has these files, it probably won't hurt to leave them there as they are, but changes and modifications to the files will be ignored in the future.To set this up on a per-project basis (which will affect anyone checking out the project), you would add the svn:ignore property to the project directories where files are likely to be stored. For example, to exclude a directory named
build
from the top-level of your project, you would do something like this:From now on, the build directory in your project will be ignored by subversion. For more on this, see the documentation at http://subversion.tigris.org/ or issue the
svn help
command for more information.EDIT: Added more based on comment... dunno how I missed that part of the original question!! Sorry :)
Unfortunately, removing the files that you now want ignored from the repository is a manual process, although, if you know exactly which files they are, you could write a little script that people having this problem could run (in the future, the svn:ignore property would keep them from ever having to repeat it, and it has the advantage of being able to be easily modified when the need arises).
To remove the files that you don't want from the repository, but keep the local files around, follow these steps:
svn rm --keep-local filename
svn rm
command for each file, commit your working copy.Because this may have the side-effect of deleting files from people's current working copies if they haven't updated their config files, I highly recommend using the svn:ignore property on the repository directories. That way, when people update, they won't unexpectedly have files deleted because they haven't modified their
global-ignores
parameter yet.