Rules to Better Branching and Builds - 5 Rules
Optimize your branching and build strategies by checking your workspaces when defining new builds and adopting effective naming conventions. Understand the advantages of using branches over labels, know the right moments to branch in Git, and foster a collaborative environment to swiftly address build issues.
When defining a build, you should always check the Workspace tab. Only the workspace relevant to your build should be included.
If you have a number of Team Projects open from the same TFS Project Collection, all of their workspaces will be included by default. You should remove those workspaces that aren’t being used otherwise the build server will get the source for every workspace in this list before starting a build.
You should always follow a naming standard when naming your builds. This helps you identify their purpose at a glance.
The build name should have the following suffixes, depending on their purpose:
- .CI - For continuous integration builds. These are triggered automatically and do not deploy anywhere.
- .CD.[Environment] - For continuous delivery builds. These are triggered automatically and deploy to an environment. You should specify which environment it deploys to as well.
Good Example: We have two continuous delivery builds to our staging environment.
Although labels are useful they can be changed after they have been created with no way to tell that they have been changed.
Fact #1 : Creating a branch of 1GB of source code does not increase the size of your database by 1GB. It just adds a bunch of pointers. Only the differences are actually stored. Fact #2 : When you delete a branch it is not really “deleted”, you are just ending the history. You can undelete at a later time.
Tip : Find deleted items by ticking “Tools | Options | Source Control | Visual Studio Team Foundation Server | Show deleted items in the Source Control Explorer”
The best way to handle continuous development and deployment is following GitHub Flow. The basic idea is to always deploy from master , and to create a feature branch for every feature. When the feature is complete, it is merged back to master via a pull request, which provides a trigger for other developers to build.
Using this strategy, master is always production-ready and deployable.
Note: This rule applies to git. For branching advice in TFVC, see when to branch.
The process
Assumption
Set up build system to deploy from the master branch
Your build systems should always deploy from master, and should automatically deploy on every commit to master.
Since master is always being deployed, it must always be in a deployable state.Step 1 - Create a branch
a) Create a "feature branch" for every PBI
When starting a PBI from the task board, create a branch from master with a descriptive name for that feature.
git branch start-stuff
Figure: Bad example - Branch name is not descriptive
git branch create-basic-web-application
Figure: Good example - Branch name describes the intent of the change
It is critical that this branch always comes off master, not another feature branch. Master is the only branch that is mandated to be in a deployable state, so any other option is unsafe.
Obviously, we're creating a lot of branches and merging a lot under this strategy - and that's ok. Be sure to keep your PBIs small (as per breaking large tasks into smaller tasks), and you will not have much merge pain.
The benefit of creating feature branches is to reduce the number of conflicts and churn of unfinished code during development of a feature. It allows features to be developed independently of each other and reduces the amount of expensive "pull latest from the server, and rebuild everything" operations, as well as greatly limiting the impact of commits with unfinished code.
b) Code away and complete the PBI
c) Create a commit - it will contain your changed files on your local PC
While working, commit frequently to this branch with nice, descriptive messages. For example: "Added a field to hold the product category to our timesheet read model" or "added a column to the timesheet summary UI for the product category".
git commit -m "Started report change"
Figure: Bad example - Commit message does not describe what was changed
git commit -m "Added a product category filter to the timesheet summary report UI"
Figure: Good example - Commit message describes exactly what was changed
d) Push your changes to your remote Feature Branch
Step 2 - Open a pull request (to merge from your current branch to the master)
When the change is complete, or when you want feedback on anything, open a pull request to merge the branch back to master. The pull request is more than just a request to merge, it is a request to have someone review the code and architecture, or image and to discuss any issues. Resolve these issues with more commits in the branch before continuing.
Tip: A best practice is to have another developer review your work and then approve.
It is easy to chalk this step up as busy-work, but it is one of the most valuable parts of the strategy.
Assumption
Deploy the changes to a staging environment. This allows the features to be tested before being merged to master.
Some prefer to move this step to after the merge, especially when using a release management tool like VSTS Release or Octopus Deploy (see Do you use the best deployment tool). If you decide to go this route, remember that master should remain deployable and production ready at all times and that all branches come from master. If skipping this step, ensure that you have CI on your feature branch to ensure that your branch compiles and passes all tests before merging.
Step 3 - Merge and Deploy (to master)
Once everyone is happy and everything is tested, complete the pull request, which will merge back to master. Ensure you are not using the "Fast Forward" merge option (git), or details about the branch will be lost - it will appear as though all work was done in master. Being able to see the feature branches in the git log is very useful.
After you completed the pull request, make sure you also delete the branch that you made the pull request of. Deleting your completed branch will not just help yourself in the long run, but also everyone else. Having too many branches especially a stale one will confuse developers on what "may" be in progress, moreover it would cause so much pain to the future developer when they have to do a clean-up and the branch author has left.
Otherwise, you can do it before you complete the pull request by ticking delete branch option.
Once merged, master should immediately and automatically be deployed (in a perfect world, to production).
If you or someone on your team has broken the build, the whole team should swarm to fix the problem immediately.
It is PERFECTLY ok to have the CI build go red, that is what is there for, but when the build goes red the team should go immediately into corrective action mode and make sure the build goes green again.
Two things should be done:
- Get it Green
- Find out WHY it went green locally but red on build server. This may indicate something is brittle in the application structure, and that is the underlying cause – and should of course also be fixed.
Bad Example: Too many broken builds in a row.
Good Example: Broken build was fixed immediately.