Well, that happens sometimes: a big bad piece of the early development changes suddenly leaks to the production. But if you have Capistrano and Git everything comes up pretty manageable.
On CookEatShare we use the next deployment scheme:
- the master branch of our git repository is the development mainline, it's accessible to all team members and used mostly to share intermediate work results; most of us do the development in the private branches, rebase those to the master branch, then merge into master and push/pull the changes;
- the staging branch used, well, for the staging. The master branch is being merged to the staging when there is something to demonstrate. Usually it's a working code with possible bugs here and there;
- the production branch is current cookeatshare.com state: staging is being merged there only if everything is fine and the current bugs were fixed. Capistrano deploys to the production from that branch.
We don't have a strict release management discipline. We're a startup and everyone is wearing multiple hats, so deployment can be done by anyone who has something to show. Sometimes it really screws up everything.
So, what to do if some very important patch came into the production and took some hairy guests with him. First, is, of course, cap deploy:rollback. After that we have our previous state restored but there are still 2 problems:
- Our important patch is somewhere deep inside of the current mainline and it's still not applied to the production;
- The production branch is no longer pristine, it has all the undesired commits.
So here's the thing:
cap deploy:rollback
git co production
Now take a look at git log and find the commit with patch (let's say it is P)
git diff P^1 P > our.patch # Keep patch at hand
git reset --hard PREV # PREV is pristine production state before unfortunate merging
git apply our.patch # We can do it in separate branch forked of current one if we need to rebase to other branches.
Actually this patch didn't apply at the first try, so I had to do some small changes, fortunately the patch was tiny, only 5 lines changed in 3 or 4 files.
git ci -a -m "Patch applied" # I use aliases for commit, checkout, status etc.
git push origin production --force # Note '--force' as it's not fast-forward push
cap deploy
Phew, thanks git for making all of this so easy (and there's maybe even easier way if not in the middle of the night with CEO on Skype).
Anyway, to correctly apply the patch to the production it should be forked from the production itself, merged back, and then rebased and propagated to other branches). But sometimes things are not that nice and maybe this will help you (if you use separate branches for the multistaging).
Finally, some sleep!