Sunday 22 February 2009

Merge individual git commits to "future" branches

At work we are currently looking at moving from CVS to Git. After reading Pragmatic Version Control with Git I am convinced that skipping Subversion and going directly to Git is the best way forward. This book is highly recommended - I bought the electronic book for myself and a paper copy to pass around to key people in the office.

With CVS we currently have a feature that enables developers to check in changes on an older branch and have then automatically applied to future branches, unless they explicitly say otherwise. For example if a developer commits a change to the 08_04_10 branch it will be automatically applied to the 08_04_11 and 08_04_12 branches, if they exists.

Replicating this feature in Git looks like it will be easy using a script run from post-commit hook. The script could either apply the commits to future branches immediately or just make a note of the commit id and branch so that an external script can apply the commits at a later stage. I expect that we'd go with the latter so that the "merge forward" functionality can't adversely affect the commit, but we may end up with a hybrid approach.

Some quick-and-dirty pseudo-code for the above:

In post-commit hook:
COMMIT_ID=$(git-rev-parse HEAD)
DATE=$(date +%s)
echo $COMMIT_ID > /path/to/$BRANCH_NAME/todo/

In merge_forward script:
#!/usr/bin/env perl

my $base_dir = "/var/tmp/$$";
mkdir( "$base_dir" );

my %todo{'TPL_8_4_10'} = ( 'TPL_9_1', 'TPL_9_2' );

foreach my $branch (keys %todo {
opendir(TODO, "git clone '$future_branch'") == 0 ) {
foreach my $commit_id (@commit_ids) {
system("git cherry-pick -x $commit_id");

I found the git-rev-parse HEAD command above in a mailing list discussion about whether or not the post-commit hook scripts should be passed the commit id. Also take a look an Benjamin Meyer's blog entry about commit hooks for how to get the list of files that have changed.

No comments:

Post a Comment