In unserer Firma benutzen wir git für das Fahren von Development, Preview und Live.
Der master enthält dabei per Definition immer eine releasebare Version. Preview ist ein Branch, der vom master gebrancht wurde.
Wird ein neues Feature implementiert, erfolgt dies in einem Feature-Branch, welcher nach fertiger Implementierung in den Preview gemerged wird. Das Preview-Tag wird dann auf HEAD gesetzt und auf den Preview-Server publiziert.
Nach der Abnahme wird das Feature in den master gemerged. Vor dem Publish wird das letzte Release getaggt (für evtl. nötiges Rollback) und das Live-Release-Tag auf den HEAD gesetzt. Das Live-Release-Tag wird dann auf den Live-Server publiziert.
Der Publish-Prozess ist dann ein (bei uns recht featurereiches) Script, welches einen Publish-Checkout auf den Release-Tag updated und per rsync die Live-Installation updatet und ggf. noch einige Aktionen ausführt (Caches leeren, crontab updaten u.s.w.)
Alternatiov könnte die Live-Installation auch nur ein Clone sein, den man per git auf den aktuellen Release-Tag updatet. Dann spart man sich das Publish-Script.
Für die Zusammenarbeit bei der Entwicklung und als zentralen Sammelpunkt haben wir einen gitosis-Server. Wobei die Feature-Branches nicht auf den gitosis-Server gepusht werden sondern erst der Merge in den Preview-Branch bzw. master submitten das Feature auf den gitosis-Server.
Gelegentlich werden durch Mergen des master in den Preview-Branch Fixes, die direkt im master eingebaut wurden, in den Preview nachgezogen. Und hin und wieder (so einmal im Jahr) kann es nötig sein, den Preview-Branch neu aus dem master zu erzeugen - hauptsächlich, um die Anzeige in gitk nicht zu unübersichtlich werden zu lassen.
Dass der Preview parallel zum master geführt wird ermöglicht es, auf dem Preview schon mehrere Features gleichzeitig zur Abnahme einzubauen und trotzdem die Reinhenfolge der Merges in den master flexibel zu halten.