Branching Workflow (by example)

git can be used with many branch management schemes.  The branching scheme used by the CASA team is described in this article using three example work requests that proceed along different routes in the build and test workflow: 

  1. The simplest case where no conflicts occur during merges and no continuous integration (CI) tests fail. 
  2. An automated build and test failure where the fault is found in our own code changes. 
  3. An automated merge failure that requires manual intervention.

IMPORTANT: Automated merges are disabled due to compatibility problems with submodules. Developers must merge master to their branch periodically.


As a prerequisite to the workflows described below we clone the BitBucket repository.  This creates a local copy of the full repository where we can do our work until we are ready to push our changes back to the BitBucket server.  Under normal conditions, a clone is done once per machine, per developer.  Rather than making a new clone for each JIRA ticket, we will simply create then check out a new branch from the BitBucket server to our local machine. 

Example 1: Development activity with no conflicts or failures

We are ready to begin work on JIRA ticket CAS-1234.  The following figure shows the branch diagram for this activity.  In this diagram time progresses roughly from left to right.

Branch diagram without conflict

To begin, the master branch exists on the BitBucket repository.  After cloning this repository, we have a copy of the git repository with the master branch on our local machine.  The BitBucket repository is called "origin" because it is the remote source for our local repository.  The local repository includes a full history of origin's code changes (log) at the time of the clone.

The BitBucket repository also contains branches created for JIRA tickets, both in development and completed; CAS-0123 is an example of a branch in development.  While we work, other branches may be created, developed, and merged back into the master branch on origin.  In the above figure, CAS-3456 is an example of concurrent development activity.  A new branch for CAS-3456 is created on origin and merged back into master with no effect on our local repository. 

In JIRA, we create a branch off of origin master (node A) and name it "CAS-1234."  We then check out this branch from the BitBucket repository to our local repository.  Now we have two branches, master and CAS-1234, with CAS-1234 checked out as the active branch.  We begin work on CAS-1234 using our local repository.  We write code and commit changes to our local repository with no effect on origin.

We conclude the first stage of our development work, commit our changes and push our commits back to origin (node B).  This push triggers Bamboo to perform an automated merge of the master branch onto our branch (CAS-1234) on origin.  Our local repository is unaffected by this automated merge.  After the successful merge, Bamboo builds our branch and runs test suites 0 and 1.  We receive an email from Bamboo telling us that the build and test cycle completed successfuly. 

We then begin work on the second stage of our assignment.  When this is finished, we commit our changes and push our commits back to origin. Bamboo builds and tests our branch just as it did before.  We receive an email from Bamboo again telling us the build and test cycle completed successfuly. 

We have finished our work assignment, so we change the status of our JIRA ticket from "Scheduled" to "Ready to Verify."  Bamboo detects the state change in our ticket and automatically queues up test suite 2 for our branch.  When this test passes, Bamboo notifies us by email.  The project manager or group lead then verifies that automated testing ran properly and moves our ticket to the "Ready to Validate" state.  The validation is successful, the ticket state is changed to "Resolved," and the ticket is assigned back to us.

We update the appropriate user documentation and we are now ready to merge our branch back into master.  We initiate a pull request using the BitBucket pull request interface.  The pull request is approved by the appropriate build manager and the branch is merged back to master.  If we wish, we can delete this branch in our local repository, as development is complete and the branch is up-to-date in origin should we need it later.

Example 2: Development activity with build and test failure

In this example, we follow the same procedure as described in Example 1, above.  We push our changes back to origin (node B), but in this case Bamboo's automated build and test cycle fails.  Bamboo sends us an email documenting the failure.  We identify the problem as being in our code changes.  We correct the problem, finish our development work, and push our commits back to origin.  The build and test activity concludes successfully, as described in Example 1.

Example 3: Development activity with merge conflict

In this example, we will explore the procedure for resolving a merge conflict.  This activity begins just like Example 1, above.  A graphic representation of this example is shown in the following figure.

Branch diagram with conflict

We create branch CAS-1234, check out the branch from the BitBucket repository, and do our first stage of development work.  Prior to pushing our commits back to origin, we checkout and update (pull) the master branch (node C), which includes the commits in CAS-3456 which have been merged into the master branch.

In our local repository, we then check out the CAS-1234 branch again and manually merge master into CAS-1234, producing merge conflicts between our branch and the updated master branch.  We make the necessary changes to resolve the conflicts and commit the changes.  We push the changes to origin.

With the merge resolved and the push done, the build and test procedure continues as described in Example 1 and our branch is ultimately merged with master upon completion of the pull request.