What is it?
Because I couldn't make git-svn keep my git commits (only the rebased, SVN-like version is kept, so pretty much all commit information is lost),
and it was tiresome to keep two branches in sync by hand,
I wrote a script to do it for me. It’s called
git-mysvn because I couldn’t think of a good name. It started small, but since I decided to
make it public, I tried to make it more robust and understandable, and it blew up.
Basically, it manages the history in two forms, the git history (in branch
master) and the SVN history (more precisely, the git-svn history).
Commits that belong to both histories are “meta-commits”. The script keeps references to the actual git and SVN commits corresponding to the
latest meta-commit. These references allows it to fix things up when the SVN and git histories diverge starting from the latest meta-commit.
- works with an empty SVN repo, by creating a dummy initial commit and pushing everything else on top
- works with a nonempty SVN repo (the user can specify which commits correspond to the latest meta-commit if needed)
- when fetches changes from the SVN repo, manages the integration of the new commits in the git history (rebasing on top of the latest meta-commit, then rebasing the new git commits on top of the resulting commit)
- should be POSIX-compliant (tested with dash)
Requirements: the script uses git, svn, find, and a standard Unix toolbox (rm, mkdir, touch, cat).
The git history must be in the
master branch (though it's configurable in the code), and it is
advisable to keep it linear, to avoid having to solve conflicts twice.
How to use it
Simply put it somewhere in your
PATH, then go to the git repo and do
git mysvn init URL-of-the-SVN-repo
to initialize things (it will clean all traces of a former SVN remote).
Warning: if the SVN repository was not empty, you'll get a warning, telling you to set up the references of
the latest meta-commit. You can safely ignore it, unless the last commits in the SVN history are not in the git history
(i.e., the SVN tip is ahead of the latest meta-commit). When you're sure everything is fine, run
git mysvn commit to push your git history into the SVN repo.
If the the master branch contains merge commits with conflicts, you will have to resolve them again
while rebasing; when you're done, just execute
git mysvn continue.
Afterwards you simply have to keep your work in the master branch, and when you feel like pushing it to the SVN repo, do a
git mysvn commit.
If there have been commits to the SVN repo in the meantime, they are merged into the git history (on top of the latest meta-commit),
then new git commits are rebased on top of them. If there were conflicts during this rebase, resolve them. It leaves everything in a clean
state, you can then execute
git mysvn commit again.
Some other potentially useful commands:
git mysvn cleancleans up all (?) traces of previous uses of git-svn.
git mysvn fetchonly fetches new SVN commits and insert them into the git history, without committing anything.
git mysvn helpshows a short help.
The script is available here.