Workflow
Permanent / Semi-permanent Branches
The only permanent branch is the master
. Master is always stable and always supported. Bugfixes and releases merge to this branch.
There will also be long-running feature branches. These branches will be created when a feature becomes stable and doesn't have an active release branch to go into. They will be deleted after a certain period of time after the merge to the proper release branch.
The release branch will be deleted after a certain period of time after the merge to the master
Temporary branches
A number of temporary branches are used. Each feature/bug should be contained on its own branch. Every feature or bugfix branch should be cut directly off of master
. Each temporary branch lives till the moment when the release branch it was merged to is merged to the master
.
General Workflow
The issue possible workflow pathes are:
* new
-> ready
-> new
* new
-> ready
-> merged
States:
* new
- The issue (feature or bug) was created, or returned for additional work.
* ready
- The pull request for the issue is made. The contributor is sure that it is ready to be merged to qcubed codebase.
* merged
- The pull request was tested and approved by core contributor. it is merged to the own branch on the qcubed repository.
There are two issues involved in the bugfix or feature lifecycle: * the original proposal or bug report issue, and * the pull request issue.
Note that the pull request issue is autogenerated for each pull request and is just a one possible solution for the original issue. That is what the original issue is for - it is used to describe the proposal or the problem, while the pull request's issue is used to describe the specific way this pull request implements to solve the original issue. In other words, the original issue answers the question "What is going wrong?", or "What should be enhanced, and why?", but the pull request's issue answers the question "How it was implemented and why this solution was choosed, if there where alternatives?"
The general rule is to name the pull request issue after the name of the original issue it solves. It saves time to figure out what this request is for. Also, the second rule is to reference the original issue number with a # sign in the pull request's message body, e.g. "This pull request implements the feature #NNN". It helps to navigate to the original issue from the pull request, since the link is autogenerated in this case, and a "reference" comment is generated in the original issue.
Features
Features should begin as a conversation. An enhancement
issue is opened against the right available release milestone, and requirements can be hashed out there.
A branch will be cut off of master by the developer assigned to the feature named feature-{feature name or issue number}
or, simply, f-{feature name or issue number}
. Note that the branch for the feature should not be made in the qcubed repository directly, it should be created in the developer's own fork.
If the feature is being worked on by more than one developer, second developer should fork the repository of the first one, and send pull requests against it.
Feature branch developers need to keep a close eye on master and merge in any bugfixes that are accepted. This ensures a minimal number of surprises once the feature is merged into an upstream branch.
Once the feature is ready to be tested, the pull request is made against the qcubed repository. Make sure that qcubed repository contains the feature with the same name you want to pull in. See the section called "Features that require a new branch" below for more info.
The qcubed maintainer tests the pull request and, if test has passed, merges the pull request to the proper feature branch into the qcubed repository. The original issue this feature was inspired off should be closed with a comment like this: "The feature is implemented in the pull request #NNN". If test has failed, maintaner closes the pull request with an appropriate comment message.
Naming Conventions
- Branch
feature-{feature-name}
orf-{feature-name}
[to be deleted after stable release]
Bugs
Bug fixes are handled slightly different from features. A bugfix branch is created from an issue. A branch should be cut off of master
by the developer with a name in a format bug-{issue number}
or, simply, b-{issue number}
. Everything else is the same as in a feature case.
The one important difference: after the pull request for a bugfix is accepted, the resulting 'bug-{issue number}' branch in the qcubed repository is merged into master
immediately. This is good because users can pull bugfixes as they become stable and merge into their existing instance of qcubed. This also makes it easy for the core contributors because they can easily merge bugfixes into their feature branches and we shouldn't have to worry about merging bugfixes for a release.
Naming Conventions
- Branch
bug-{issue number}
or, simply,b-{issue number}
[to be deleted after stable release]
Releases
When enough features are stable, a release branch named rc-{x.y.z}
is cut off of master
. The stable features are merged into this release branch and tested together. Once they pass testing, the branch is tagged {x.y.z}
. This tag is an annotated tag. This means that it's a tag that doesn't just get deleted - it stays for long term. It is then merged back into master and thus made available for stable download.
The rc-{x.y.z}
branch should be removed after a certain period of time after the {x.y.z}
release is adopted.
Naming Conventions
- Branch
rc-{x.y.z}
[to be deleted after 'bake-in' period of merge into master]- Tag
{x.y.z}
[Last thing that happens before merge into master] [annotated tag]
Community contributions
We encourage everyone that wants to contribute to do so. Anyone can fork the framework and submit pull requests to a feature branch or bugfix branch. These requests will be reviewed by core contributors and (if up to [[standards|Standards]]) applied as features or bugfixes accordingly. If you would like to contribute to QCubed, the following steps will help ensure that your contribution is included in the next release:
-
Fork the framework repo. Clone your fork to your local machine with the command
git clone git@github.com:myUserName/framework.git
. Note that a clone only pulls the master branch initially. This clone automatically sets up a "remote" for your github fork called "origin" (hence the git push origin branchname command). -
Set up your "upstream" remote. Since we're on distributed version control, we can have multiple remote repositories at once. This is key to using github (and git in general). You can name this remote anything you want, but convention dictates naming this "upstream". Do this with the following command:
git remote add upstream https://github.com/qcubed/framework.git
. -
Notice that to clone your fork you used git@github.com:qcubed..., but to set your upstream you used https://github.com/qcubed... This is because the "upstream" is read-only. Even if you have write access to qcubed/framework, I highly recommend using the https:// protocol to avoid accidentally pushing to the upstream framework.
-
Check for an existing feature branch to work on and pull it locally. If you would like to do this in the terminal as well, you can with:
git branch -a
. Doing this will list all branches locally as well as all remote branches in the formatremoteName/branchName
. Pull feature branches from "upstream": -
Make sure you're on
master
locallygit checkout master
(you can find out what branch you're on at any time by typinggit branch
into the terminal.) and create the branch:git checkout -b branchname
(following the conventions outlined above). If it says you already have that branch, don't panic, just take off the -b and try again (-b means "create this as a fresh branch off of the branch that I'm currently on). -
Pull the branch from your fork:
git pull upstream branchname
(where "branchname" is the name of the branch you are pulling). This will bring your local branch totally up-to-date with everyone else. -
Write some code Please make sure your code is documented and follows the [[standards|Standards]]. When you are finished writing:
- Make your local commit as usual (Recording Changes to the Repository).
- Push updates to your fork as necessary
git push origin branchname
- You need to make sure you're still in sync with the
upstream
repo before submitting a pull request. Do this with:git pull upstream branchname
wherebranchname
is the name of the branch you're on. - You also need to make sure your branch has any bugfixes that may have gone into
master
since your branch was cut. Do this by: - switch to
master
:git checkout master
- pull
master
from "upstream":git pull upstream master
- upload any changes to your fork on github:
git push origin master
- switch back to your feature branch:
git checkout branchname
- merge in master:
git pull origin master
-
Push your code to your
origin
repository (your fork):git push origin branchname
wherebranchname
is the name of the branch you're on. -
Create a pull request. Make sure you make your pull request to the proper branch. If you're contributing to a feature branch, make sure your pull request is going to the same feature branch on qcubed/framework. Same idea for bugfixes. Pull requests made to the wrong branch may still be merged in, but repeated pull requests to the wrong branch from the same user will be rejected with a request to resubmit to the correct branch.
If there is no feature branch or bugfix branch for your code, just request one! Open an issue on the proper repo and attach an 'enhancement' tag for a feature or a 'bug' tag for a bugfix and describe the changes you're proposing. One of the core contributors will quickly review your request and make you a branch asap.
Merging a merge request
As a core contributor, you may have to handle merge requests from time to time. There are 2 main types of merge requests we will receive - features (or bugs) that require a new branch and features that already have a feature branch. We will cover instructions for both methods here.
Prepare a Core Contributor's working copy
Even if you are a Core Contributor, it is a must to not mix things. You should have two working copies installed: the first one is for ordinal work on your own features or bug-fixes - it's setup is covered in a section of "Community contributions", and the second one for doing merges to the main qcubed repository. These two must be separated to not having the write access to the main qcubed repository from the working copy of your own fork.
In order to prepare the second working copy for merges, do the following: clone the qcubed repo to your local machine with the command
git clone git@github.com:qcubed/framework.git
. Note that a clone only pulls the master branch initially. This clone automatically sets up a "remote" for the main qcubed repository named "origin" (hence the git push origin branchname command).
That is all. Now you can use this main working copy to do the merging.
Features that require a new branch
For features that don't have an existing branch (usually these features will be requested to merge into master
. It is very important that you never merge anything directly into master), follow these steps:
- On your main qcubed working copy, switch to
master
:git checkout master
- If you have uncommitted changes on your current branch, git may ask you to commit or stash them before switching branches. You can do this by simply typing
git stash
or by committing the changes if they're ready. - Create a new branch locally off of master:
git checkout -b branchname
- the
-b
flag means "new branch" - Push the branch to qcubed/framework
git push origin branchname
- If you had to stash changes before you switched to master, switch back to the branch you were originally in and type
git stash apply
. This will put back any changes you had stashed.
Now the main qcubed repository has the branch named branchname
. Contributors can use it to target their pull requests to.
Features with an existing feature branch
Features that have an existing branch are easy to merge. After reviewing the change locally and making sure the request is set to go to the correct branch, you should be able to just click the big green "auto-merge" button. If that button is not green or has a warning and the request is going to the correct branch, you need to investigate why git is telling you there may be a conflict. If you're not sure what to do, open an issue and ask. Do not merge features into the repo if you aren't sure that they're getting merged correctly.
Do the merge/review changes
We assume here that the pull request already has a branch on the main qcubed repository. If not, follow the section named "Features that require a new branch" above.
In order to review changes provided in the pull request, follow these steps:
- On your main qcubed working copy, switch to the branch in question
branchname
:git checkout branchname
- If you have uncommitted changes on your current branch, git may ask you to commit or stash them before switching branches. You can do this by simply typing
git stash
or by committing the changes if they're ready. - Make sure your working copy is fresh:
git pull origin branchname
- Make sure the
brachname
is up to date with themaster
:git pull origin master
- If any changes were pulled in, push them before do anything else:
git push origin branchname
- Add a remote for the fork of the developer that is making the request:
git remote add jamescmunro https://github.com/jamescmunro/framework.git
Note the https:// protocol usage. git remote add jamescmunro
- add a remote named jamescmunrohttps://github.com/jamescmunro/framework.git
is the read-only address of my fork- Pull in the newly added fork:
git pull jamescmunro branchname
git pull
... pull from a remote repositoryjamescmunro
is the name of the remote you added earlierbranchname
is the branch of the remote you want to merge- Review and test the code
- Push the changes to qcubed/framework
git push origin branchname
- Remove a remote for the fork of the developer that is making the request:
git remote rm jamescmunro
- If you had to stash changes before you switched to master, switch back to the branch you were originally in and type
git stash apply
. This will put back any changes you had stashed.
More to come