Using Git with SVN repository – simple case howto and benefits

Introduction

If you use Apache Subversion repository you may want to use some benefits of Git source control managment system. But you may not have possibilities to switch from SVN repository to Git completely.

One of the large benefits of Git over Subversion is possibility to commit when you don’t have internet connection. Another one is availablility of commit history when there is no internet connection as well.

You may achieve mentioned benefits with Git-SVN functionality described at Git Book chapter “Git and Other Systems – Git and Subversion. There is also git svn man page available.

You will find below how to set up and use some Git benefits when you still continue to work with SVN centralized repository.

It is expected you have some basic knowledge about Subversion and Git before setting up communication between them.

I use Git version 1.9.2.msysgit.0 downloaded from here.
SVN version on client PC is 1.8.8.

Getting SVN repository to Git local repository

To start working you should first get SVN repository locally and has it in Git format.

It can be done with the following command:

git svn clone https://path/to/svn/repository -T trunk –username john

john is a name of user to SVN repository

Note, this command fetches trunk only. If you need to copy SVN repository branches and tags to  Git, please refer for more information to Git Book chapter “Git and Other Systems – Git and Subversion”, section “Getting Started”.

Since Git retrieves all SVN revisions of the selected path it may take a while depending on the size of the SVN repository folder and history, whether SVN repository is local or remote. Several hours is quite usual. Note, this is one time procedure.

Anyway you can see progress on the console to have an idea how long it takes to perform initial checkout.

After obtaining repository locally you may observe a history of it without internet connection already, which is usual for Git, but not possible for SVN.

I was surprised that the size of Git repository including quite long history is 10% less than the size of the same SVN working copy without history. Although Git has 3 times more files than SVN, but you can reduce it to some small amount by running command “git gc“.

You may have obtain branch list to run following command:

>git branch -a
* master
remotes/trunk

You should also consider here how to manage ignored SVN files. There are several choices.

You may run following command:
git svn create-ignore
This command creates .gitignore files in every folder.

Note, retrieving ignoring information could take quite a while.

Another option is to run following command from the root of Git repository:
git svn show-ignore > .gitignore

In this case you obtain one file, which looks more convenient, especially if you don’t want to bloat SVN repository with Git-specific files.

You may either commit this single file to SVN repository or not.
Note, .gitignore should be updated from time to time; it does not get updated automatically if the set of ignored files is modified in SVN repository.

If SVN folder was renamed then Git imports revisions which were commit after renaming only. History before rename in SVN repository is not imported with Git-SVN.

You may find the following page on the subject Checkout remote branch using git svn useful.

Commit changes from Git to SVN

You can work locally as usual with Git, committing several times:
git add *
git commit -m “commit message”

Note, you don’t need Internet connection here as opposed to Subversion.

If you want to send all local changes to centralized SVN repository you just need to run following command:
git svn dcommit

After this every local commit will be sent to SVN as separate SVN commit.

Note, timestamps of changes in SVN will be the time of executing dcommit, not original moment of Git commit. Git repository will also reset dates locally to make them equal to SVN ones. That is why it is suggested to commit changes to central repository as soon as possible. Well, this rule is a best practice regardless of the version control system you use to reduce conflicts between commits of different developers.

It is suggested to perform dcommit from the root of Git repository; this is where “.git”-folder is located. Otherwise you may obtain error similar to the following:
Cannot dcommit with a dirty index. Commit your changes first, or stash them with `git stash’.

You are suggested to update changes from SVN repository. Otherwise you may obtain the following error:
ERROR from SVN:
Merge conflict during commit: Your file or directory ‘<filename>’ is probably out-of-date: resource out of date; try updating
Note, commit still may be actually complete to SVN repository, if there is no conflicts despite the message above.

You also should commit all changes locally to Git repository before commit them to SVN. Otherwise sending changes to SVN repository may fail.
But if you want to commit modification partially you may find Git stash command useful.

  1. Commit all changes you want to send to SVN repository to git repository with “git add” first
  2. Save modification locally with stash command:
    > git stash
  3. Commit changes to svn repository as usually:
    > git svn dcommit
  4. Restore local modification in git repository:
    > git stash apply
  5. Drop local stashed modifications:
    > git stash drop

You may also find command “git stash list” useful to view all stashes. You can find more info about stashing in Git book chapter “Git Tools – Stashing”.

Update changes from SVN repository to local Git repository

To obtain changes from SVN repository the following command should be executed:

git svn rebase

It is suggested to call it before any commit to SVN.

Note, Git revision is SHA-1 hash unlike SVN one which is integer number. To find SVN revision corresponding to Git one you just need to view comment of commit; Git adds corresponding SVN revision number there for you.

It is suggested to commit changes to local Git repository before updating from SVN to avoid following error:
update-index –refresh: command returned error: 1

If you do not want to commit changes before update you may use the same trick with git stash as described for committing changes above.

View change log

You may view change log with a command:
git log
There is also command which outputs the log in SVN friendly format. It shows revisions which are already committed to SVN repository only:
git svn log
Both commands work offline unlike svn log.

You may also use git svn blame which is also similar to it SVN counterpart svn blame, but available offline. Note, you should specify file name with path, starting from the root of Git repository regardless of your current folder. To obtain consistent blame you should execute git svn dcommit before blame, otherwise revisions which are not yet in SVN repository will not be considered in blame.

Dealing with SVN externals with Git repository

There is no clean and perfect solution here.

There are different solutions based on either Git submodules, separate utilities, ad-hoc scripts, symbolic links or specific strategies concerning commits or checkouts. There are mixed approaches which involve several items enlisted.

In general it might be not a large issue if approach used has some drawbacks. This is because externals are updated rarely in most cases.

You may find different approaches in following pages:

Graphical user interface tools for Windows users

If you use TortoiseSVN for SVN, you may also want to use TortoiseGit for Git with GUI. You can perform most commands mentions above with it.

Note, you still need to download and install Git package.

Unsupported features and suggestions

Git-SVN does not support tracking file history after renaming folders. Most probably this feature will not be implemented in future. Refer to git-svn(1) Manual Page, section BUGS for details. Files in renamed folders are considered new. This may have influence for some logging commands, e.g. for git svn blame and native svn blame as well because info about renaming is not committed to SVN.

Some commands in Git skip empty folders. If it is important for you to preserve them, then you may use key --preserve-empty-dirs which is available for Git commands.

There is also discussion about merges in Git and SVN at page After “git svn clone”, I still don’t have fantastic branch-merging commit?

One more page is about useful Git-svn tips.

Accounting info mentioned above I would suggest to use Git with SVN during usual development only. I mean adding, deleting or modifying files. But if you want to make some significant changes to SVN repository or perform changes which looks specific for SVN, I suggest to use native SVN facilities. If you still want to use git-svn bridge for such specific operations I suggest to read and try these feature in some test environment.

Since Git is a more flexible VCS than SVN I would also suggest to use most basic features only, because many Git operation cannot be expressed in terms of SVN.

Please avoid using git merge, use just git rebase. Keep revision history as linear as possible.

Notes about migrating from SVN to Git

Since you may already tried to use Git with Subversion you may decide to switch to Git completely.
I collected some links which might be good starting points during migration:

Leave a Reply

Your email address will not be published. Required fields are marked *