My project has a Subversion repository on a network file system, and a new team would like to access it using Git, and be able to commit to it and get updates from it.
W
Here is what I've come up with:
Create the git-svn
repository if it doesn't exist already:
git svn init --std-layout
The master
branch is created automatically to track the trunk
.
To avoid name ambiguities with Subversion-tracking branches, make the original Subversion branches show as remotes/svn/
: go to the newly-created git-svn
repository and run
git config svn-remote.svn.fetch trunk:refs/remotes/svn/trunk
git config svn-remote.svn.branches branches/*:refs/remotes/svn/*
git config svn-remote.svn.tags tags/*:refs/remotes/svn/tags/*
rm .git/refs/remotes/*
git svn fetch
Create a Subversion-tracking branch for each Subversion branch:
for BRANCH in $(svn ls /branches/); do
git branch $BRANCH remotes/svn/$BRANCH
done
Make sure no non-Subversion-tracking branches are created on the central Git repository:
# Used by hooks/update:
git config hooks.denyCreateBranch true
git config hooks.allowDeleteBranch false
cp .git/hooks/update.sample .git/hooks/update
chmod +x .git/hooks/update
Allow pushing to the central Git repository:
git config receive.denyCurrentBranch ignore
git config receive.denyNonFastForwards true
git config push.default current
And create the post-receive hook to reset and send the commits to Subversion:
cat .git/hooks/post-receive
#!/bin/sh
date >> receive.log
git reset --quiet --hard
while read LINE
do
BRANCH=${LINE##*/}
echo Updating $BRANCH
git checkout --quiet --force $BRANCH
git svn dcommit
done 2>&1 | tee -a receive.log
git checkout --quiet --force master
chmod +x .git/hooks/post-receive
The reset is necessary, because otherwise the current branch is out-of-date after each receive.
Finally, create the hook to get updates from Subversion:
cat .git/hooks/svn-rebase-all
#!/bin/sh
date >> .git/svn-rebase.log
git reset --quiet --hard
for REF in .git/refs/heads/*
do
BRANCH=${REF##*/}
echo Updating $BRANCH
git checkout --quiet --force $BRANCH
git svn rebase
done 2>&1 | tee -a .git/svn-rebase.log
git checkout --quiet --force master
chmod +x .git/hooks/svn-rebase-all
And call it from the Subversion post-commit hook:
cat /hooks/post-commit
cd
. .git/hooks/svn-rebase-all
chmod +x /hooks/post-commit
Instead of using a single git-svn
central repository, one can use a bare central Git repository and an intermediate non-bare git-svn
repository, as in this answer.
I chose to use one non-bare git-svn
repository which is also the central repository.
Anyone can work on the project using Git by cloning
and pushing to it, or using Subversion by checking out
and committing to it.