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 will find below how to set up and use some Git benefits when you still continue to work with SVN centralized repository.
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
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
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.
- Commit all changes you want to send to SVN repository to git repository with “git add” first
- Save modification locally with stash command:
> git stash
- Commit changes to svn repository as usually:
> git svn dcommit
- Restore local modification in git repository:
> git stash apply
- 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:
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:
- Using SVN repositories as git submodules
- Manipulation with folder structure http://blog.tsunanet.net/2007/07/learning-git-svn-in-5min.html
- Using SmartGit with its custom files in Git repository. Page SVN Integration, section “Externals (Normal Mode Only)”
- SubGit is tool for a smooth, stress-free Svn to Git migration. Create writable Git mirror of a local or remote Subversion repository and use both Subversion and Git as long as you like.
- Helpful scripts to keep external up to date
- Using recent feature of Git modules
Graphical user interface tools for Windows users
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.
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:
- Converting a Subversion repository to Git. This article contains step by step conversion process from SVN to Git. You may also find links to another useful articles there. Many subjects are covered, but I have not found there how to deal with SVN externals.
- Cleanly Migrate Your Subversion Repository To a GIT Repository
- Git Submodules: Adding, Using, Removing, Updating
- SubGit is tool for a smooth, stress-free Svn to Git migration.
- Ruby tool for importing existing svn projects into git
- You may try SmartGit for migration.
- If you use SVN with MSBuild, e.g. SvnInfo from MSBuild Community Tasks, you should eliminate it. E.g. you may decide to replace it with Git calls via MSBuild Exec task or use other approaches. You may also find the article MSBuild: Add Git Commit Hash to AssemblyInfo useful. Note, if you still use Git locally only, you may consider to ignore SvnInfo commands if it is acceptable; this is simple approach to avoid errors.