I have nearly the same workflow as proposed by Greg Hewgill except that in general I rebase interactively my local commits between each dcommit so as to glue ("squash" in git terminology) then into a single commit onto the svn server.
It makes the commits on SVN more efficient as otherwise, an svn revision will be added for each of your local git commit and I found it not desirable in most case.
So to summarize, here is my workflow:
- I have a "master" branch that is the only branch that I dcommit from and that clone the SVN repository (
-s
assume you have a standard SVN layout in the repository trunk/
, branches/
, and tags/
):
git svn clone [-s] <svn-url>
- I work on a local branch "work" (
-b
do the checkout into "work" after branch creation)
git branch -b work
- commit locally into the "work" branch (
-s
to sign-off your commit message). In the sequel, I assume you made 3 local commits
...
(work)$> git commit -s -m "msg 1"
...
(work)$> git commit -s -m "msg 2"
...
(work)$> git commit -s -m "msg 3"
Now you want to commit onto the SVN server
- [Eventually] stash the modifications you don't want to see committed on the SVN server (often you commented some code in the main file just because you want to accelerate the compilation and focus on a given feature)
(work)$> git stash
- rebase and resolve conflicts between "work" and "remotes/git-svn"
(work)$> git svn rebase
At this level, you will have conflicts between you local commits in the "work" branch and the last unique glued dcommit. Simply run the following command to skip the commits in "work" that were previously glued :
(work)$> git rebase --skip
Continue until the rebase is successful (resolve the eventual other conflicts). Use the following command to ensure everything is fine:
(work)$> git log --graph --oneline --decorate
- go back to the master branch and svn rebase there (to update from the SVN server)
(work)$> git checkout master
(master)$> git svn rebase
- Now it's time to merge with the "work" branch
(master)$> git merge work
Resolve any merge conflicts (there shouldn't be any at this point)
- Now you want your 3 commits to look into a single one on the SVN server. All you need to do is to type:
git rebase -i HEAD~3
This launch your $EDITOR
and allow you to perform what's referred to as an "interactive rebase". The idea is to "pick" your first commit and "squash" the others. You should end with something like that:
pick 08464ae msg 1
squash 8750643 msg 2
squash af6f7ae msg 3
# Rebase 05e760e..21e20fa onto 05e760e
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Save and quit the editor. You will then have your $EDITOR
that is executed to edit your commits (good to maintain a single sign-off signature)
- finally commit on the SVN server
(master)$> git svn dcommit
- Go back to work and eventually recover your stashed files:
(master)$> git checkout work
(work)$> git stash pop