Using git to track changes to mephisto

written by Cristi Balan on 2007-08-14

Prerequisites

svn and perl bindings

You might have to recompile svn if you don’t already have the perl bindings. I’m on OS X and I got these svn binaries with perl bindings

git

Git is being actively developed so various bug fixes and features are usually not in the stable release. You’ll need to get the source and compile it.

Compiling is just make && make install if you want it just for your user. You can grab a recent tgz from this git-snapshots page

Setup

You’re going to need a svn repository where you can commit. You can create an empty repository and or just use your current mephisto customization one, if you have it.

Tip: If you create an empty repository, make sure you create a trunk directory in it. It will help if you later decide to use some svn branches:

$ svn mkdir svn://server/blah/trunk

1. Create local git repositories

To clone a svn repository without grabbing all the revisions, you need to know a commit number that actually exists on branch you want to mirror. Many times this is not the number you get when you do svn update.

The easiest way to find it is:

$ svn info http://svn.techno-weenie.net/projects/mephisto/trunk | grep “Last Changed Rev:” | sed -e “s/Last Changed Rev: //”

On to the clones…

For mephisto, we’re going to start from a revision earlier than the latest so we can see how updates from mephisto will get into our repository:

$ git-svn clone -r 2939 http://svn.techno-weenie.net/projects/mephisto/trunk mephisto

For our svn repository we want all the history so we don’t pass a revision:

$ git-svn clone svn://server/blah/trunk blah

Now, let’s create a branch for mephisto into our blah git repository.

$ cd blah $ git remote add mephisto ../mephisto $ git fetch mephisto

We used git remote add to create a name for our mephisto repository for easier access.

Let’s check what branches we have so far. Your output should be the same.

$ git-branch -a
  • master
    git-svn
    mephisto/master

At this point, it depends on wether you are using an empty repository or not. Use the next step (2a) if you’re starting on a new repository.

Jump to 2b. if you already have customizations in a svn repository.

2a. Empty svn repository

Merge the mephisto/master branch in the current master:

$ git merge mephisto/master

Then push the changes to our svn repository:

$ git-svn dcommit

Note: The git-svn documentation says to do a git-svn rebase before doing dcommits. Just this once, don’t do that.

2b. Existing mephisto customization

If you did the step above(2a), ignore this and skip to step 3.

Things are a bit more complicated if you’re trying to reuse a svn repository and want git to properly handle merges. This is just the way I’ve been able to do this, I’m sure there must be a better way. If you know of a better solution, please let me know about it.

First, I assume you have no local changes in your git repository. Use git-status to check and git-reset to undo any local changes. If you really really want to lose all local changes do git-reset —hard HEAD.

Now, let’s try a merge:

$ git merge mephisto/master

The result should be a bunch of conflicts for each change that happened on the mephisto tree since you last updated your customization. I’m thinking this is because there’s no common ancestor for the master and mephisto/master branches.

You could now go through all the changed files, remove the conflict markers, commit and it would work. But that kinda sucks. Let’s try something else..

Undo the local changes form the attempted merge with:

$ git-reset —hard HEAD

We’re going to manually apply the changes so we don’t get conflicts. We’ll use git-log to find the most recent update we did from mephisto. Scroll down until you find it and grab the commit hash.

$ git-log

Once you got that, we’ll use it to grab and apply the changes from mephisto:

$ git-diff 6c9f4058f13ad3e37cb8bd3d43315c914cdaf396 mephisto/master > changes.diff $ git-apply changes.diff

You might have some conflicts now so go ahead and fix them. Use git-status to see which files have conflicts. After you fix a conflict, use git-add blah to tell git about it.

After doing the conflicts, add the new files that we got form the merge to the index:

$ git-add .

Remove the changes.diff form the index:

$ git-rm —cached changes.diff

We also need to tell git about any deleted files (let me know if there’s a better way to do this):

$ git ls-files -z —deleted | git update-index -z —remove —stdin

Let’s see what we’ll commit:

$ git-status

If everything looks ok, go ahead and commit to git and push changes to our svn:

$ git-commit $ git-svn dcommit

3. Daily usage

Once you got the initial dcommit in your svn, things are the same regardless of wether you started with an existing mephisto customization or not. You can happily use git branch form master, do a bunch of commits, merge back, etc.

Getting changes from mephisto

Make sure you don’t have any uncommited changes first and do:

$ git fetch mephisto $ git merge mephisto/master

Pushing new changes in svn (and pulling changes from svn)

Make sure you don’t have any uncommited changes first and do:

$ git-svn rebase $ git-svn dcommit

Final notes

I spent a lot of time working this things out and I hope this helps some people to get up to speed faster. Please let me know if things can be done better or simples.

Resources

Options:

Size

Colors