Here is how to kick start feature development:
git clone --recursive https://github.com/<username>/cloudstack.git
git flow init
git checkout -b <feature-branch>
or if you use git-flow git flow feature start <feature>
git checkout <feature-branch>
This sets your local working set to the branch you want to pull the latest changes into. git fetch upstream
git rebase upstream/<feature-branch>
git merge upstream/<feature-branch> --no-ff
git config reviewboard.url
https://reviews.apache.org
post-review
git push upstream <feature-branch>
git branch -d <feature-branch>
git flow feature finish <feature>
Committers will not be looking at your repo by default. Therefore, alert the cloudstack-dev mailing list of your work and periodically request the incremental commits you make be reviewed.
It is also best to work on feature branches rather than working directly on develop, even in your private fork. When the patch is ready for submission push the squashed patch through reviewboard. If the patch is sizeable and touches many projects in the repo, best to break it down into smaller chunks for easier and quicker review by multiple committers. Don't use github's pull request feature, but in the reviewboard patch notes, you can include the upstream you request a committer to pull from to preserve useful history.
Holler for help on the lists if you're stuck and ever need help.
# Set the name of the user for all git instances on the system git config --global user.name "Firstname Lastname" # Set the email-address of the user for all git instances on the system git config --global user.email "your_email@youremail.com"
Here are some key guidelines for how to make a clean commit. See the linux kernel patch guidelines for more.
It is more important to create clean commits than it is to follow all the branching rules. If your commits are clean, branching/merging mistakes can be resolved by looking at them. The reverse is not true.
Coming from centralized version control like cvs or svn, you may be used to committing you work only once a task is finished. An svn commit goes to the remote repository immediately, so committing work in progress breaks flow for your colleagues that then have to update their working copies. There can also be a race to get your work in first so that you don't have to be the one to sort out the merge.
Leave that mindset behind! Git is truly distributed version control, so you can and should commit without push. In a git workflow, your code-test-code cycle should become
Then when you end a session (when you finish a task or feature, or you reach a milestone in its development), you think about pushing your changes.
git log
to remember what commits you didgit rebase -i
to clean up your history (optional; see below)git commit --amend
to clean up your commit message (see below)git fetch upstream/...; git pull --rebase
to replay your changes against the latest upstreamgit push
to send your commits upstreamBecause we use feature branches, none of this involves scary merging. Only once a feature is complete does it get merged into the develop branch, and at that point you want to spend some time to check that your changes don't conflict.
Apply, basically, the same principles to commits that apply to source code.
Commits should do one thing and do that thing well.
Either move files, or refactor/rename some method, or fix license headers, or change the build, or change a version number in a build file. Don't combine multiple such things into one commit.
This helps make sure that the many different changes going on at the same time can be merged together without issues, and make it possible to go back in time to figure out what happened.
In the case of documentation files, it can make the job of the translation teams more complicated, as it becomes difficult for them to determine exactly what content changes need to be translated.
Please make your commit messages descriptive. Avoid committing changes to many files in one go with a generic, vague message. Instead, commit each file (or small, related groups of files) with tailored commit messages.
A good commit message should look like this:
Header line: Explain the commit in one line of 50 chars After a blank line, the body of commit message is a few lines of text, explaining things in more detail, possibly giving some background about the issue being fixed, etc etc. Use bullets if possible: - Line 1 - Line 2 etc. * Start works too, instead of - The body of the commit message can be several paragraphs. Use proper word-wrap and keep columns shorter than 72. That way "git log" will show things nicely even when it's indented. Include the CLOUDSTACK-xyz jira issues related to this commit, if any, somewhere in the message. Reviewed-by: Individuals who reviewed, or link to review on review.apache.org Reported-by: whoever-reported-it, if applicable (usually this is recorded in the Jira bug) Submitted-by: give credit to other individual for any patch submission committed by you Signed-off-by: Your Name <youremail@yourhost.com>
Note that there exists a git hook to prepare a commit form for you, located at tools/git/prepare-commit-msg. One simply needs to link to it in order to use it:
ln -s ../../tools/git/prepare-commit-msg .git/hooks/prepare-commit-msg
Please use a logical prefix, which should be:
For a feature that takes several weeks to flesh out, these guidelines may result in dozens of commits. That's absolutely fine, git's implementation means that there is basically no cost at all to keeping all that history around. Having the history available of what it took to get to a finished feature is very useful; the branch/merge history for that future provides a summary of all those different commits.
For experimental work where you have to do a lot of undo/redo work, perhaps abandoning part of a solution completely and replacing it with another, you may choose to hide some of the 'mess' of that history, creating a cleaner alternate history, pretending you got everything right the first time. Cloudstack currently doesn't have a strong rule for or against that. If you want to do it, two key commands are git rebase -i
and git checkout -p
. When you do it, remember: do not rebase on branches you have pushed upstream.
Be mindful of the branch that you are working in. Please use feature branches for bigger changes, and support/hotfix branches for bugfixes that have to go into multiple releases. Please be mindful that just because you have commit privileges does not relieve you of the obligation to develop in the open, which means communication on the cloudstack-dev list.
Using the git-flow command line tools is recommended but completely optional.
As a committer one of your responsibilities is to review and commit patches from others. The patches must pass through reviewboard, the bug tracker or the mailing list so they can be tracked and so they can be considered a CONTRIBUTION per the apache license/CLA.
Patches should be applied via git-am (in other words, don't just use a diff, it records no author information).
Discussion thread | Vote thread
After the 4.4.0 release, cloudstack has decided to move to (a variant of) the git-flow branching model. The switch was made XXTBC august, 2014. The setup is as follows:
This is the proposal for first cut
develop
from master
release/4.5
from the develop
A hotfix is a bugfix that is done to an existing release and/or release branch.
Since 4.4 can't be merged to/from master, bugfixes to 4.4 need to be done twice, once for 4.4 and once for 4.5 and beyond:
hotfix/4.4-<jira-ticket>
from 4.4hotfix/<jira-ticket>
from release/4.5hotfix/4.4-<jira-ticket>
into 4.4
hotfix/<jira-ticket>
into release/4.5
hotfix/<jira-ticket>
into release/4.5
and pushrelease/4.5
into develop
For bugfixes that don't need to go into 4.5.x, normal git-flow can be followed.
In git-flow it is customary to delete release branches after a release. We won't do that. Instead minor releases get a long-term support (LTS) release branch. This means it will be a bit easier to create patch releases for multiple releases.
Imagine we have released 4.5.0 and 4.6.0, and we want to do a hotfix that is to be part of 4.5.1 and 4.6.1:
hotfix/<jira-ticket>
from release/4.5 git flow hotfix start <jira-ticket> release/4.5
mvn -P ... install && ... smoke test ...
git commit -a
git push upstream hotfix/<jira-ticket>
hotfix/<jira-ticket>
into release/4.5
hotfix/<jira-ticket>
into release/4.5
and push git checkout release/4.5
git pull --rebase
git merge --no-ff --edit hotfix/<jira-ticket>
git push upstream release/4.5
develop
git checkout develop
git pull --rebase
git merge --no-ff --edit release/4.6
git push upstream develop
while it should be possible to merge your hotfix branch into develop, the possibility exists that other hotfixes were already merged into the release but not yet into develop. If you merge your hotfix but not those previous hotfixes, comparing the history of release and develop branches gets a bit more difficult. So, we merge all the hotfixes on 4.6 to develop.For bugfixes that don't need to go into 4.5.x, normal git-flow can be followed (see below).
Calling git merge with --no-ff ensures a merge commit. This commit documents the history that there was a specific hotfix.
Calling git merge with --edit allows editing the merge commit message. Use this to add any comments about the application of this hotfix to this release.
See above under 'Quick Start'. This should be the default way of working for most changes.
New features should come with tests and those should go onto the feature branch.
When improving test coverage for existing functionality, you should still create a feature branch if there's a lot to the test (moving code around, refactoring to reuse existing code, changes to test tools, etc). For simply adding a new test, see below.
Fixing a simple bug that
Can be done directly on develop.
However, since when you start the bugfix you typically don't know exactly what the fix will be, it's simply good practice to create a local bugfix branch anyway. Basically, whenever you do a context-switch to pick up a new task or JIRA issue, you probably want to branch. The workflow difference in this case is that the branch you create is local to your machine; you never push it upstream. For example:
Start work:
git checkout develop
git pull --rebase
git checkout -b bugfix/<jira-ticket>
...write test...
git commit -a
...code code code...
git commit -a
...test fix test...
git commit -a
Check that you're done: mvn -P ... install && ... smoke test ...
Cleanup and make neat clean commit(s)
git pull
git rebase -i develop
git commit --amend
git checkout develop git merge --ff-only bugfix/<jira-ticket>
git branch -d bugfix/<jira-ticket>
Push the changes:
git push upstream develop
Besides the normal git-flow commands, remember to update version numbers (in maven pom.xml, in marvin setup.py, in systemvm scripts, ...should have a confluence page...).
git checkout develop
git pull --rebase
git flow release start x.y develop
...update version number to x.y.0-SNASPHOT...
git push upstream release/x.y
git checkout develop
...update version number to x.y'-SNAPSHOT...
git commit -a
git push upstream develop
Don't use git flow release finish
, it will delete the release branch.
git checkout release/x.y
git pull --rebase
...update version number to x.y.z...
git push upstream release/x.y
git checkout master git pull --rebase
git merge --no-ff --edit release/x.y
git tag -a vx.y.0
git push upstream master
git push --tags
git checkout release/x.y
...update version number to x.y.z'-SNAPSHOT...
git push upstream release/x.y
This is very similar to starting minor release, but you start from the release branch, not from the develop branch.
git checkout release/x.y
git pull --rebase
git flow release start x.y.z release/x.y
git push upstream release/x.y.z
git checkout release/x.y
...update version number to x.y.z'-SNAPSHOT...
git push upstream release/x.y
This is very similar to finishing a minor release. You shouldn't have to update version numbers in release/x.y in this case (since you did that at patch release start; see above), but it's probably good to check.
git checkout release/x.y.z
git pull --rebase
...update version number to x.y.z...
git push upstream release/x.y.z
git checkout master git pull --rebase
git merge --no-ff --edit release/x.y.z
git tag -a vx.y.z
git push upstream master
git push --tags
git checkout release/x.y
...version number is already at x.y.z'-SNAPSHOT...
Patches encapsulated all the changes you want to make to another branch. Patches are used to communicate the changes that you want incorporated into Apache CloudStack.
Patches should be created with git-format-patch - and you should specifically be basing that against the branch you are targeting for inclusion, so for instance using our above example from the <feature-branch>
branch we'd run:
$ git format-patch -s develop
The above would produces a patch file for each commit in the directory (unless you specified one with -o /path/to/patch/folder).
If you've a series of commits that you want to put into a single file, try
$ git format-patch -s develop --stdout > ./mycommits.patch
CloudStack currently doesn't utilize Github pull requests. We ask that you post patches on Review Board.
git config reviewboard.url
https://reviews.apache.org
post-review
We can and occasionally do accept patches send via e-mail to the development list, or patches attached to JIRA issues, but Review Board is the standard. Please use it.
For big changes that involve multiple commits, review board unfortunately does not support patch sets. When sensible, it's preferable to create multiple reasonably-sized, reviewable commits, and multiple reviews on review board. If you've made really small/clean commits, that may be too much hassle for you and/or the reviewer. Don't spam reviewboard! In those cases, please do submit the squashed patch using post-review
anyway, but then edit the description to include a link (i.e. to a branch in a cloudstack fork on github, or to a git am
mbox somewhere) for communicating the full history.
If the patch to be applied gets the commit details in the header, then use
If it's just a raw patch, then use
Git assumes that if you have commit privileges that you are to be trusted, and generally this is a good thing. However, occasionally people are lured by the dark side of the force and when something doesn't merge cleanly, or their push doesn't work - they are tempted to whip out the --force and make it work. PLEASE NEVER DO THIS. It's is almost universally wrong. Please tell us about your problem on cloudstack-dev and let us help you fix it.
The coding standard for CloudStack says that unix line endings (LF) are used instead of CRLF (Windows line endings). You should set your editor and git configuration to behave properly.
For more information:
http://help.github.com/line-endings/
http://git-scm.com/docs/git-config
In short, please don't. If non-committers have a patch 95% of the way - comment and tell them what is necessary to make the patch acceptable. Let them fix their own patch and resubmit. Yes you can probably fix things more quickly, but it's important for community growth (both in number and experience) that folks do this themselves.