Saturday, July 19, 2014

Stop Checking in the Settings!!

Ideally configuration hangs off of the build setting or (better still) the deployment process takes care of the configuration. If you're using Puppet or Octopus to deploy your code then this is super easy. Having this sort of infrastructure isn't always feasible especially on smaller projects with smaller teams. The project I'm working on at the moment is one such codebase. We share settings.xml files, there are many of them and each developer needs to configure these files as per their own environment as well as the deployed environments - per feature. This is a problem we are very aware of and we have scheduled tickets to take care of it but in the mean time I'm going to look into how we can use Git to limit the pain of this.

I am a massive culprit for checking in settings files - everybody does it - especially the nub on the team (me)... It's really annoying to the poor person who does an update after the point and then has to rework the settings files. So here are a couple of ways we can fix this (this is very basic git stuff so if you're well versed on Git you'll be well aware of the following!):

Open up a command prompt and navigate to where you keep your git repos. Mine are normally in d:\git

Lets start with a fresh plate, run the following:

We've just created a brand new git repo for us to play with. very straight forward. We don't want to work in master so lets create a new branch:

Now that we have the dev branch we can make our settings file.

Add some dummy dev environment config to the settings.xml file. Now we can add that to the dev branch and commit it.

Now that that's safe and sound we can create our feature branch where we will want to do some work and manage our own config:
Put some code in test.cs so we can commit that into the wayne branch

Now lets customize the settings.xml file:

Make the dev specific settings feature specific so you know if this works or not when we come to doing the switcheroo. Now we want to commit the feature specific settings into the feature branch:
Now we'll continue to do some more work:
And commit that into the feature branch
OK so now we have a dev branch with some settings in, we branched from dev to create a feature branch, did some work in that branch, configured the settings file to make it specific to that branch and then did even more work, big day in the office. What we want to do now is to merge the work in the feature branch to the dev branch - but we definitely do not want the settings from the feature branch to show in dev, that's just going to wind everyone up.
To do this we can revert the commit we made to push the settings into the git branch. We can check the log to see the commit and revert it. To do this run the following:

This will yield something like the following (type q to exit the log):
As you can see the commit with ID "965f41809225abbe2ed2b74d6e162e27c9c18a72" so to revert this commit we can issue the following command:
And then we can safely merge our feature branch into dev:
Open up settings.xml and verify it's as expected - dev settings, not feature settings.
So that was one way of making sure we don't merge stuff we don't want to merge. If we wanted to do some more work in the feature branch and get the settings back we can use the same approach above to undo the commit made by git revert - git simply creates a compensating action to revert the commit by and this creates another commit - so we can just revert the commit created by the compensating action (which will create another compensating - git is just event sourcing after all!). Another approach is cherry pick commits from the feature branch. This will apply a single commit to the branch you are merging into. Here is the general gist of it:

Git is powerful stuff - cherry picking is basically the converse to the 1st approach. It shows how useful doing small, discreet commits can be. In general there are only a small handful of git commands that I use frequently - you can do so much with a small amount of git commands it's ridiculous. But there are some extremely useful, more "advanced" features which really bring Git into it's own. I'm still learning Git but one thing I have found is that using it properly really pays off and there is always a sane solution to whatever insane mess I find myself in!