#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}` or `f-{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:

1. **[Fork the framework repo](https://help.github.com/articles/fork-a-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).

1. **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.

1. **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 format `remoteName/branchName`. Pull feature branches from "upstream":

 * Make sure you're on `master` locally `git checkout master` (you can find out what branch you're on at any time by typing `git 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.

1. **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](http://git-scm.com/book/en/Git-Basics-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` where `branchname` 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` where `branchname` is the name of the branch you're on.

1. **[Create a pull request](https://help.github.com/articles/creating-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 the `master`: `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 jamescmunro
 * `https://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 repository
 * `jamescmunro` is the name of the remote you added earlier
 * `branchname` 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