views:

43

answers:

1

Hello,

My situation:

I've recently joined on the front-end side of an established project that involves a growing number of instances of a rails app, each of which which differ in some aspects (views, styling, settings etc) but which all share the majority of their back end code.

Our Git repo has a number of branches looks something like this:

master
apple
banana
cherry
...
strawberry
tangerine
...

Where each fruit-derived branch is holds the production code for a production instance.

(Master isn't used for a live deployment but contains all the shared code and is what we'd clone from to set up a new instance.)

My problem:

Work specific to a single instance is simple enough, taking place in that in branch (or a dev branch of it) etc etc...

However, if I need to make a change that will affect all the sites in the cluster I do that at the moment in a dev branch and merge it into master, and then (what's bugging me) have to manually check each production branch out in turn and merge master into it.

Even my humble code monkey brain can see that this does not scale well.

At the moment we have something like 8 production branches, so it's not that bad, but the plan is for growth and by the time this gets to even 20 (let alone 50+) it's going to be a serious pain. It's also going to be my personal pain, as I'm the one who is likely to be dealing with it on a day to day basis.

So, my actual questions would be:

  • Is there something in the core git functionality that I'm missing that will let me elegantly merge from master into n other branches in one fell swoop? (unlikely I think, but worth the ask nonetheless)
  • Alternatively, might there be a way to do this with crafty some shell scripting? (of which I might add, I know very little, and understand even less)

If the latter of these can anyone help me get started/point me in the right direction?

Many thanks in advance for your time and help.

+3  A: 

Before I answer this, I want to be very clear that this is only a good idea in cases like this where the branches to merge into are production branches, not development branches. If you've found this post looking for a way to merge integration branches (master) into all your topic (development) branches, the answer is that you almost certainly shouldn't (see here).

Okay, and the real answer. There's no built-in way, because (assuming it's not a fast-forward) you really do have to have the files checked out for git to do its merge magic. Fortunately, you're not actually doing much (git checkout && git merge) so it's no trouble to write a script. You could complicate this with a config file, or even add some custom stuff to .git/config (e.g. git config branch.<branchname>.productionbranch true, and then use git commands to check which branches have that flag set), but the simplest way would be something like this:

#!/bin/bash

production_branches=( branch1 branch2 branch3 )

for branch in ${production_branches[@]}; do
    if ! ( git checkout $branch && git merge master ); then
        exit
        # Exit on the first error
        # If you want to just plow ahead, do something like this:
        # git reset --hard       # make sure there aren't merge conflicts in the tree
        # failed_merges="$failed_merges $branch"  # remember for later
    fi
done

# if you plowed ahead above, print the branches which failed to checkout+merge
# if [ -n "$failed_merges" ]; then
#     echo "Failed merges: $failed_merges"
# fi

There are, as always, many improvements you could make. For example, you could use some git commands to check if master has already been merged into a given branch, and avoid checking it out. If you're moving on past failed merges, you could do the checkout and merge separately in case it was the checkout that failed (that might imply dirty working tree, which means they'll all fail). Hopefully this is enough to get you started though!

Jefromi
Hey Jefromi, thanks for the very clear and useful answer - time for me to get my hands dirty I think...
meta