Git is a super-cool VCS that encourages a distributed workflow. Sorry, this post is full of enterprisey jargon because it is meant for them.

Usually, most enterprises have development teams that consist of smaller independent sub-teams with little communication among them. They have a workflow where the code is first tested (against dummy data) on a development machine and then on a staged machine with production data before the code is finally promoted.

The development teams have no access to production data because it could be confidential or too cumbersome to setup. The staging teams (in enterprise jargon called "integration teams") usually consists of senior folks (probably under NDAs) who monitor the staging servers and report bugs and anomalies to the developers. Finally, there is a production (operations or ops) team that communicates with the staging team once in a while and promotes tested code.

Laborious process...eh? True, but it is a time-tested process that hardly fails (do I sound like a manager? Oh gosh!). This workflow is called the "Staged Integration Workflow".

Now imagine implementing this workflow in Subversion! Ah...I bet you just said "Painful". Git can help reduce the pain because of the way it has been designed. This article is inspired from scenarios at my previous work place. I wasn't successful in convincing a migration to Git because of a strong Subversion bias. But hopefully, this article will be helpful to some others willing to give Git a try.

So time to make a few assumptions:

  • The enterprise is using a nix variant (most enterprises are already singled out because they love the Redmond based company. If your enterprise in one among them, time to stop reading this and go pester your management for "A Real OS").
  • The enterprise has no problems using SSH.

Workflow

Git Workflow for enterprises
  • Create users for each developer (you don't have to create them if you already have user accounts setup). Create 3 additional accounts for the git development, staging and production repositories.

  • Create SSH keys for each user and copy them to the corresponding repository's authorized keys ie copy the SSH keys of the developers into the development repository's user account, the staging team's SSH keys into the development repository. Finally, the production team's SSH keys into staging repository.

  • Create a git project in the Git development repository user.

    $ mkdir git_project
    $ cd git_project
    $ git init
    # Add, edit and finally commit your files to the repository
    $ git commit -m "Commit Message" .
    
  • Now the developers clone this repository on their dev boxes, create multiple branches according to their comfort and push their changes back to the server after running the test-suite.

    $ git clone dev_user@dev_server:/path/to/git_project
    # Makes his own branches and works on features and pushes
    # code after the test-suite passes.
    $ git push
    
  • The staging server is setup the following way:

    # The following steps are done for the first time
    $ mkdir git_project
    $ cd git_project
    $ git init
    $ git remote add dev_repo dev_repo_user@dev_server:/path/to/git_project
    $ git pull dev_repo
    $ git checkout -b dev_branch dev_repo/master
    $ git checkout -b staging_branch
    
  • A tag is created to refer to the commit when the pull is performed. This tag is used as a reference for bug reports and internal communication. Then pull from the development repository is done on a pull request from the developers or periodically (say end of day).

    $ git checkout dev_branch
    $ git pull dev_repo dev_branch
    # Create a unique tag
    $ git tag tag_`date +%Y%m%d`
    $ git push dev_repo tag_`date +%Y%m%d`
    # The stage user runs a test against production data
    # After it passes, the dev_branch is merged with the
    # staging branch
    $ git checkout staging_branch
    $ git merge dev_branch
    
  • A similar process happens on the production side.

    # The following steps are done for the first time
    $ mkdir git_project
    $ cd git_project
    $ git init
    $ git remote add staging_repo staging_repo_user@staging_server:/path/to/git_project
    $ git pull staging_repo
    $ git checkout -b staging_branch staging_repo/staging_branch
    $ git checkout -b prod_branch
    
  • Once more for clarity:

    $ git checkout staging_branch
    $ git pull staging_repo staging_branch
    $ git checkout prod_branch
    $ git merge prod_branch
    

The steps that I have written are quite verbose. If you are comfortable with the usual Git terminology of origin (default remote repo) and master (default refspec), you can reduce the number of lines. It is also possible to host the repositories (dev, staging and prod) on one machine, as 3 different users (useful for small enterprises that can't afford many machines).

It is possible to implement the same workflow with Subversion but it can be very painful and confusing. What applies to Git will also apply to any other DVCS like Mercurial and Bazaar.

So go ahead and refine your workflow and don't forget Git, the stupid content tracker.