
(each commit is represented by a circle).
(dotted lines: extra merges required)
Prologue
- This thing is written fast, and definitely have mistakes but should give a good overview of the approach.
Overview
We have a use-case very similar to yours, and this is the most optimized solution that we've found until now.
You will need 3 different branches:
- master (this is your main branch, all the -- useful -- code that developers write comes here at last)
- production
pre-release -> this is a temporary branch. it's there between the time that you are demoing something to the client and the time that that thing goes to the production server.
- take note that production and pre-release are eventually both an older version of master branch, i.e. master excluding some of its the latest changes. So any changes that are directly made to pre-release(based on client request) should be merged to master. also any changes in the production branch (critical bug fixes) should be merged to master branch as well as the pre-release branch if it's active. This is the most important thing to consider, otherwise you'll end up in a mess very similar to having more than one code base in one git repository.
For routine tasks:
The developer Foo would:
git pull
git checkout -b new_feature
and then writes her code and commits often to the new_feature branch.
Once she's done:
git pull << to get the latest changes on master (in the picture you see Foo's branch is 2 commits behind master's ~HEAD)
git rebase -i master << -i to be interactive, so she can pull out some of the local changes she's made e.g. local changes config files or customized loggers for her own benefit, etc.
git merge --no-ff master << merge the changes with master
git push << push to the repository
Test server:
Once you're good enough for testing/demoing to client, you can create a temporary branch:
git pull
git checkout master
git checkout -b pre-release
You may need to have some custom configs for your test machine so you can have a branch (test_server_local_changes) and serve it to the user. when you have new pre-release branch then do: git pull and git rebase -i pre-release
At this stage if a client asks for changes, a developer should branch out from pre-release and, after making changes merges, merges his branch with both master and pre-release.
Production server:
Once your client approves the changes:
git pull and git checkout production and git rebase pre-release
You may want to serve production branch. Or if you have custom changes specific to your production server, it's better to have a separate branch for it (production_local_changes) with a couple of extra changes and always rebase it on production branch.
Critical Bug fixes:
Suppose someone will find a critical bug in your production server, then Bob will create a branch from production branch, fix the bug, commit it and then merge his branch with production server and then pull and rebase the prodction_local_changes. But then, the change will not be present in the master, so he will also need to merge with master as well, also with pre-release if it's active and rebase test_server_local_changes.
Notes
In my opinion in git (unlike SVN as I remember those ugly days of using it) users should branch whenever necessary and commit as often as it makes sense.
Each user can and should have his local branch having all his own configurations and merge it or do cherry-pick first thing when they branch off from any of 3 main branches. They can always rebase -i and remove their own local changes before they merge back to any of those 3 branches. Same goes for production and pre-release branchs, there should be a branch off them for all the configurations that are local to each.
I love gitolite and I think it's a good tool to use on top of git to manage permissions, have a kind of a central repo and make using git easier.