tags:

views:

95

answers:

3

I have 5 branches of one system - let's call them master, London, Birmingham, Manchester and demo. These differ in only a configuration file and each has its own set of graphics files.

When I do some development, I create a temp branch from master, called after the feature, and work on that. When ready to merge I checkout master, and git merge feature to bring in my work. That appears to work just fine.

Now I need to get my changes into the other branches, without losing the differences between them that are there already. How can I do that? I have been having no end of problems with Birmingham getting London's graphics, and with conflicts within the configuration file.

When the branch is finally correct, I push it up to a depot, and pull each branch down to a Linux box for final testing, From there the release into production is using rsync (set to ignore the .git repository itself). This phase works just fine also.

I am the only developer at the moment, but I need to get the process solid before inviting assistance :)

+2  A: 

git rebase is your friend.

Make your changes in your master branch as you always do. When you are done, checkout one of your other branches (say, Birmingham) and run git rebase master. git will pull in the changes you made on master between the current commit and the commit on which Birmingham is based. There are good documents on the command out on the interweb. Here are two I found

http://darwinweb.net/articles/86

http://www.eecs.harvard.edu/~cduan/technical/git/git-5.shtml

There are many others. You will find many people talking about the dangers of rebasing. Pay heed to those concerns, but I suspect the benefits vastly outweigh the risks in your case; and knowing the dangers is half the battle.

McBeth
As you say, "git rebase master" unwinds to the common parent of HEAD and master. It was after git rebase master involved 19 commits 12 of which had comflicts, that I started to look for an alternative.How can I avoid this route getting longer and longer each time?
Ian
Note that with `git rebase`, you'd lose the previous states of you branches! If you distribute a commit of London then rebase the branch, you won't be able to return to this state.
Gauthier
Right, which is the danger of `git rebase` mentioned repeatedly. I would claim that that isn't always a bad thing. Once you do rebase, then the merges are done, and you won't have to deal with them again (same with merge). The fact that the OP keeps having conflicts in the commits points to a code organization and process issue rather than a method issue. Submodules will accomplish much the same thing in the case we are examining here, but still require a more careful process and code separation than is currently apparently happening.
McBeth
@Gauthier - understood. @Mcbeth - "but still require a more careful process and code separation than is currently apparently happening." Ouch - but you correct :)
Ian
@Ian that wasn't meant as a harsh as it may have come out. Process is _hard_, especially on a project that is transitioning in size from 1 to many. If you can decouple the variants from master a little more, either method suggested should work for you, while hopefully giving you some more maintainability. I've been stalling on transitioning a hobby project away from 1 person for a while for just the process issues you mention.
McBeth
@McBeth I did not feel your remark was harsh.
Ian
+6  A: 

Two techniques can help:

  • submodules: if you have 5 "mains projects", each one composed of:
    • the common code (which get enhanced feature after feature)
    • the special code (specif graphic files or config values, one set for each site)
  • template config files

So when you develop a new feature, all you need to do for the other sites to benefit from it is to make sure their respective repo reference the latest common code repo as a submodule. Just a git submodule update to do and you are done.

Plus, with template config files, all you are storing are config values, not the actual config files themselves (they get generated).
That allows you some fine-tuning on each site, without having to "ignore" local modifications.

In conclusion: instead of trying to manage all aspects (common code, config files, special files, ...) in one repo (with all the merge and rebase that will involve), try to modularize your application.

VonC
+1 for [git-submodule](http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html).
Santa
A: 

Another technique:

Once your new functionality is in master, merge back master into all the other relevant branches.

Original state:

o---o-master
    \
     o-London

New commit in master:

o---o---o-master
    \
     o-London

Merge the new functionality into the London branch, with git checkout London; git merge master:

o---o---o-master
    \   \
     o---o-London

Note however that this might be cumbersome, especially if the number of branches increase. I don't know anything about your system, but if you can have all configurations in one branch it would probably be easier (I mean having all the five configuration files and graphics files always present in you file system).

For example with a makefile, you could choose which source files to compile and link depending on your current target configuration. In your case, a makefile can help you to associate graph files and config files with a target configuration.

It would also be nice to be able to build all your configurations without any checkouts in between, would't it?

Gauthier
A possible problem with your approach is when I have to add a new graphic. Update master and London - then merge. Which do I get? Then I need to change a graphic in master, but not London. Which do I get this time? Not London! Conclusion - have a repo for the bits unique to each install and a repo for development. Use a makefile to assemble each version in a final test location from London and development repos, and to deploy that to the production site. Sources, configs, deployment process and makefiles are all version controlled. :)I just need to find the time to build the makefile(s).
Ian