This may seem obvious, but don’t use git push like CVS commit. Repositories should be accepting commits by pulling them, not pushing them. CVS commit may be your integration strategy in a simple world without branches, but git push shouldn’t be used for that.
In the land of ASIC development, where a CVS commit is instantly shared with all the ASIC designers, the worst that can happen is someone unintentionally commits a file on a branch. Then what? You go talk to the verification guy (why do they do always know how to fix CVS?) and admit your mistake. He fixes it and everyone gets the fixed up repo on their next update, no biggie. Not so much with git.
With git, as soon as you have pushed the commits, the central repository branch on which you just pushed looks exactly like the local repository branch it was pushed from, with the commits you wish you had done on another branch, and the commits you should have reverted before continuing, but more devastatingly, with the incorrect merge you should not have done. Sure, git gives you the ability to correct all your mistakes IN YOUR LOCAL REPO, but once you’ve pushed them to the central repository, it’s like a printed newspaper: it’s out there and there is no recall, only further editions. Actually, you can fix an incorrect merge, but wouldn’t you want to avoid them in the first place?
So instead of having developers push to the integration repository, the integration manager should obtain the code through a git pull. If the integration tests pass, the commits are then pulled into the release repository by the release manager, where everyone can pull from. If the tests fail, the commits are taken out of the integration repository (where no one can pull from), the contributor is notified, and the integration manager processes the next integration request.
All this may seem obvious, but today when an incorrect merge between two branches was pushed, effectively merging the branches on the release repository, it became clear to me that the workflow needed to prevent this from happening, and that it could be done easily if two conditions were met:
- use git pull for getting code into a git repository
- use two repositories, one for integration, and another one for releases, thereby isolating the release tree from mistakes on the integration tree
You could argue that development, integration and release can all happen on different branches of the same repository, but in reality, typing git merge followed by git push is and easy mistake to make (never trust humans), whereas a CI system pulling code will not inadvertently merge two branches.
Wait, I have just found git bundle… more ways to skin the cat!