The SAVARA GIT repositories are hosted under a github organisation: https://github.com/organizations/savara
Background to the Workflow
Initially we considered using the workflow outlined in this article: http://nvie.com/posts/a-successful-git-branching-model/ (the diagram is also available in the attached file). However it has one issue, which we have not yet been able to find a solution for.
In an environment where it is necessary to maintain more than one release, then the approach of merging all changes into a single branch (master in this article) does not work. For example, if we have version 1.1 release, and are working on release 1.2 in trunk (or develop branch in the article). We release a 1.2.CR1, tagged in the master branch, but then find there is a problem in version 1.1 which requires a patch release.
Using the approach outlined in this article would cause the 'master' branch to move backwards and forwards between the tagged/released versions associated with different released versions.
Therefore currently the approach outlined below is based on the standard trunk and separate release branches approach that is used with subversion. So release branches are retained, and not deleted as in the article.
However we are borrowing ideas from this article, as well as some content outlined in the development workflow article for the ModeShape project.
As we learn more from practical use of this workflow, we may document other variations here.
Organisation of the Repository
Current Development in Master
As discussed in a few of the comments on the nvie.com artlcle, it seems more natural for the 'master' branch to be considered equivalent to trunk, and therefore represent the main area for current development. The reason being that this is the default branch when initially creating a git repository, and therefore used by small projects. So it makes sense for larger projects to also continue this convention.
However one key difference between the git 'master' branch, and a svn 'trunk', is that the 'master' branch should not be used for direct commits. As outlined in the subsequent sections, changes to the code should be performed in separate feature or bugfix branches, and then merged into 'master',
This means that the 'master' branch represents the latest snapshot of project development, but is still in a consistent state (i.e. bugfixes and features are all available in a complete form).
Developing a Feature
Features should be developed in their own branch. The name of the branch should follow the convention <jira-issue-code>, e.g. SAVARA-155. This provides a concrete link to the jira issue describing the feature.
Once a feature has been developed, it MUST only be merged into the master branch. Once successfully merged, then the feature branch should be deleted.
Creating a Release Branch/Tag
Once the master branch has reached a feature complete state, and been verified with tests, we will create a tag for this specific version. The naming convention for these tags are: version, which is like 2.0.0.Final.
For some important releases, we may want to have branches for these, like we have have SAVARA-2.2.x branch, where we will have subsequent maintenance releases, while we will make our master branch as 2.3.x. In this case, we will create a release branch. The naming convention for these branches are: release-version, where version is defined by <major>.<minor>.x format, e.g. 2.0.x
Fixing a Bug
Bugs should be fixed in their own branch. The name of the branch should follow the convention <jira-issue-code>, e.g. SAVARA-321. This provides a concrete link to the jira issue describing the bug, and a short descriptive name to help as a quick reference.
Once a bug has been fixed, suitable tests provided and existing tests run to ensure no regression, the changes should be merged into the master branch as well as any other release branches that also require the fix. Once successfully merged, then the bugfix branch should be deleted.
QUESTION: What is the best approach to apply the change to multiple branches? Would rebasing on each branch work best?
Working with GIT
This section is only intended to provide a quick reference for some of the common operations that will be required when using git with the development workflow.
If you don't already have a github account, then it is free to set up an account, and provides benefits when handling pull requests, to enable the contribution to be reviewed.
You should also setup a jboss.org account, and sign the Contributor License Agreement (CLA), if you intend to submit contributions - otherwise we will not be able to accept them.
Fork the Repository
NOTE: The best practice for working with Git is for all contributors (both committers and non-committers) is to create a fork of the savara, and then work on their fork repository.
Next step is to create a fork of the particular Savara repository or repositories that you wish to work on. This is achieved by navigating to the relevant reposiory and pressing the 'fork' button. Once forked, then clone your newly forked repository to a local folder:
git clone email@example.com:<username>/<savara-repository>.git
where username would be your github username, and savara-repository would be the particular repository name you had forked. Note: this clone will by default have a remote named 'origin' pointing to your repository. Therefore it would be useful to establish a remote link to the main repository using:
cd <savara-repository> git remote add upstream git://github.com/savara/<savara-repository>.git git fetch upstream
This uses the Savara repository's public URL, to ensure that changes can only be committed to your own repository.
Creating a Branch
Based on the guidelines above, when it comes time to create a branch, you simply type:
git checkout -b <newBranchName> <baseBranchName>
So for example, if working on a feature, we may execute "git checkout -b SAVARA-123". This will automatically switch to the new branch, from where the work can commence.
Sync your repo with upstream
On a regular basis, and especially before pushing changes to your local repository, it will be a good idea to re-sync the branch with the main Savara repository to ensure they are kept in step. This can be achieved using:
git pull upstream <baseBranchName>
Note: it is also possible to achieve this using two separate commands, git fetch upstream followed by git merge upstream/<baseBranchName>.
Once merged, the branch can be pushed:
git push origin <newBranchName>
This will push your newBranch into remote fork.
Merging the Branch
When the work has been completed, and the branch has been locally re-sync'd and merged with the original branch from which it was derived, then it is time to merge the work back into that branch.
The approach used will depend upon whether you are a committer. For committers, a direct merge should be performed:
git checkout <baseBrancheName> git merge --no-ff <newBranchName>
The first command switches back to the original branch, and the second does the merge against the changed branch. The "--no-ff" option means that faster-forward should not be used (as recommended in the nvie article), to prevent loss of information about the change history that may be useful at some later stage to back out the change. It also maintains information about the branch from which the changes came.
Then once any merge conflicts are resolved, the final step is to push the merged branch back to the remote repository (either your own fork or Savara main repository if a committer), using:
git push origin <baseBranchName>
Question: Need to consider when it may be appropriate to use rebasing? Issue is where it potentially changes history in a repository that has other users based off the commit points that may be changed?
Question: Need to consider how to handle changes that need to be applied to more than one branch. Possibly rebasing would be useful here?
If not a committer, and therefore only pushing changes in your own fork, then you will need to issue a pull request from github.
Handling Pull Requests
Whether pulling requests for a contributor, or from a committer's own forked repository, the following steps will need to be performed:
Step 1: Check out a new branch to test the changes — run this from your project directory git checkout -b <username>-master master Step 2: Bring in the user's changes and test git pull https://<username>@github.com/<username>/<savara-repository>.git master Step 3: Merge the changes and update the server git checkout master git merge <username>-master git push origin master
Removing Unwanted Branches
As discussed in a previous section, some branches will be used temporarily for the life of the work, but are no longer required after the changes have been merged into other branches. In cases where the changes result in pull requested, then the branches may no longer be required after the pull request has been processed.
Once this is the case, then the branch can be removed using:
git branch -d <branchName>
If the branch had previously been pushed to a remote repository, then it will also be necessary to push the change:
git push origin :<branchName>