Contributing to ZeroVM¶
We love contributors! We want to make ZeroVM a successful platform with a great community. For this to happen, we want to hear how you use ZeroVM and work with you to make it better for your use cases!
To make contributing easy, we’ve documented the process we follow below. Please read through it so you know how we like to work.
tl;dr
We work like most other open source projects on GitHub. Make your changes as small commits and submit them as a pull request. We’ll be in touch and work with you to get the changes into the main tree as fast as possible!
Pull Requests¶
Please use GitHub pull requests when contributing code. We will try to quickly review and merge your code.
When you submit a pull request, a review cycle is started. The typical process looks like this:
- Jenkins makes a checkout of your branch and runs tests. This will tell you if something simple broke (so you avoid breaking the build).
- Someone will take a look at the code and give you feedback. The feedback can be about the code or the design.
- Based on the feedback the pull request is either merged directly or some changes may be needed.
- If changes are needed, you should update the commits and push again.
You will need to use
git push -f
this time. The pull request will automatically update and this starts a new review cycle.
Feel free to remind us on IRC or the mailinglist if it takes more than a couple of days for us to respond to a pull request. The IRC channel is also a great place to get some real-time feedback on a pull request.
Rebasing¶
You should make sure to rebase your code to the head of master
before submitting the pull request. That ensures that there will be no
merge conflicts initially.
If the pull request is not merged quickly, it can become outdated. This happens when other pull requests are merge in front of it and cause merge conflicts with the code you changed. You should then rebase the code again. See Rebasing Stale Pull Requests for detailed instructions.
It will generally be appreciated if you keep your code up to date in this way – even when there are no conflicts. Rebasing regularly simplifies the history.
Ordering Commits¶
Your commits should tell a story to the reviewer. You should therefore make sure to order them so they can be read like that. This means that you should:
- Begin with the easy and non-controversial changes first. Consider putting these changes into their own pull request so you can get them out of the way.
- Make sure each commit depends on the past only, not the future. It is very confusing for a reviewer to read commit A if it calls a function introduced later in commit B or C.
See Reordering Commits for details.
Fixing Your Own Mistakes¶
Nobody writes perfect code in the first try, so it often happens that you discover a mistake in an earlier commit. Please pay attention to this situation. When a reviewer sees a bug or some bad design in commit A, they will likely stop and begin write a comment about it. Even if you fix the problem yourself in commit B or C, it would have been much more helpful if you had avoided introducing it at all.
Please see Amending Commits for details on how to fix such mistakes with Git.
Writing Good Commits¶
We have collected some guidelines on how to create good commits – commits that are easy to review and understand later.
Further reading
One Change Per Commit¶
Please take care to ensure that each commit only deals with one logical change. Make your commits small – it is much easier to review five small commits than one massive commit. So try to err on the side of making too many commits. If you decide to split a commit, then see Splitting Commits for help.
Hint
It is much easier to combine commits than to split them: use git
rebase -i
and change pick
into squash
for the commits
that should be combined into one. Done!
The question is then what one “logical change” is. Here you will have to use your best judgment. Some examples of what not to do:
- Do not fix a bug and move a function to a more logical location.
- Do not fix a bug and fix an unrelated typo.
- Do not fix a bug and reformat the code for readability.
While each change might be good, please use two commits in these cases. To put it in another way, different classes of changes should not be mixed in the same commit:
- Bug fixes.
- New features.
- Moving code around (refactoring).
- Whitespace and formatting changes.
- Style changes.
- Unrelated typo fixes.
Your goal should always be to make sure that trivial commits stay trivial: a typo fix is trivial to review so you should make it trivial for the reviewer to accept the commit.
In general, you should stop when you see yourself include the word “and” in a commit message. If you feel the need to make a bullet list, then you are likely including too much in the commit. In any case, you should work with your reviewer. Try to follow their advice or explain to them why the changes really belong together.
Commit Messages¶
Writing good commit messages is an art. You want the message to be concise and to clearly explain the proposed change. Please follow this format:
topic: short summary line (less than 50 characters)
After a blank line, you can include a bigger description of the
changes. Wrap the text at about 72 characters -- this makes it
nicely centered when viewed in "git log".
Include relevant keywords for the GitHub bug tracker. Adding “fixes #123” to the commit message will make GitHub close issue #123 when the commit is merged into the main repository.
When explaining the change remember to focus on two things:
Explain what the change is. The diff technically shows this, so you should describe the change at a more high level. An excellent way to do this is to show the output before and after the change. Reviewers often have limited context so this is very helpful.
Explain why you make the change. This is extremely important and the part most often left out. The commit message is often all that is left of the intent and reasoning behind a change when someone looks at it again a year later because they found a bug that seems to have been introduced by your change.
Knowing what you changed is good, but what is really helpful in that situation is to know why you changed things the way you did. So please explain why this solution is the good solution. Explain what other solutions you investigated and why they won’t work. Doing so will save time for the poor programmer who is debugging your code in the future.
The second point is the more important point, so please try to put emphasis on that.
Why make small commits?¶
Easy to Review¶
As mentioned several times above, small commits are easier to review than large commits. Trying to understand what a patch that touches 100 lines does is often more than twice as hard as understanding two changes that each touch 50 lines.
Makes the History Useful¶
When each commit is an atomic step that takes the code from one
working state to another, the project history becomes a very useful
tool when looking for bugs. The git bisect
command helps you here.
The command runs a binary search on the commit history to help you
find the commit that introduced a particular bug.
When git bisect
finds the first commits that triggers the bug, the
real debugging can begin. If the commit it finds is small and does
just one thing, then it is normally easy to understand why the
problem.
Enables Revert¶
Sometimes it is decided that the change in the commit should be undone
– maybe the commit was found using git bisect
and it is
determined that it introduced a regression or a bug.
The git revert
command can then be used to undo the commit. It
will apply an inverse patch to the repository. Since the inverse patch
is based on a commit, this only works if the entire commit should be
undone. If there are good, but unrelated changes in the commit, it
becomes more work to revert it.
Selected Independently¶
A reviewer might tell you that some part of your pull request is
great, while another part is not so great. If you have already split
your work into small logical units, then it is easy for you to drop a
commit that is not needed. Alternatively, the reviewer can easily use
git cherrypick
to select the commits he like and ignore the rest.
Branches¶
We follow a workflow similar to Git where we maintain a branch called
stable
for bugfix releases. This branch is continuously merged
into master
during normal development – this ensures that
bugfixes are incorporated with the newest features.
As ASCII art it looks like this:
master: ----- o --- o --- o --- o
/ /
stable: --- o --------- o
All releases are made from the stable
branch. We release
bugfixes once per month by tagging and releasing
whatever code we have in the stable
branch. We make a
feature release every three months. These
are also made from stable
, but the are preceded by a merge of
master
into stable
. It looks like this:
master: ----- o --- o --- o --- o
/ / \
stable: --- o --------- o ------- o
This merge brings all the new features developed since the last
release onto the stable
branch.
Git Tips and Tricks¶
We have collected some tips and tricks for solving common problems when using Git.
Further reading
Rebasing Stale Pull Requests¶
When other pull requests are merged infront of your pull request,
conflicts can occur. You as a contributor, is often the one who can
solve these conflicts best – rebasing the code to the head of
master
will ensure this.
You rebase your pull request with:
$ git checkout master
$ git pull upstream master
$ git rebase master your-branch
This will first make sure that your master
is up to date with
regards to the upstream repository. The upstream should be the
repository you forked on GitHub (the repository living under
github.com/zerovm/
).
Now push the branch to GitHub again with git push -f origin
your-branch
. The pull request will automatically update.
Further reading
Reordering Commits¶
Modern distributed version control systems like Git gives you the
tools to reorder commits. Using the interactive mode of git
rebase
, you can easily reorder commits. While having your feature
branch checked out, you run:
$ git rebase -i master
This will open your editor with a file that shown an “execution plan” for the interactive rebase. Each line represents a commit and by reordering the lines you instruct Git to reorder the corresponding commits.
After you save the file and close the editor, Git will begin
reordering commits. If conflicts occur, you should use git
mergetool
to solve them. This starts your three-way merge tool which
should let you figure out how to best solve the conflicts.
Further reading
Amending Commits¶
When you want to change a commit to fix a bug, you amend it in the
Git terminology. If the fix concerns the last commit you made, then
simply use git commit --amend
to redo the commit. You can use
git commit --amend
as many times you want to fine-tune a commit.
If you want to fix something that committed further in the past, you should instead follow this procedure:
- Commit the fix by itself. Use
git add -p
to stage just the fix by itself if there are other changes in the same file. - Use
git rebase -i
to reorder the commits so that the bugfix is right after the commit that introduced the bug. In addition to reordering the commits, change the action frompick
tofixup
.
This will do the same as if you had used git commit --amend
to fix
the bug. With these steps, you can easily fix past mistakes.
Further reading
Splitting Commits¶
The general advice is to make small commits that do one thing. Even when you try to make small commits at commit-time, you will inevitably end up with some commits that you later decide that you want to split.
We will distinguish between two cases: if the commit you want to split is the previous commit or a commit further back in the history.
If you want to split the last commit, you run:
$ git reset HEAD^ $ git add foo.c $ git commit -m 'foo: fixed #123' $ git add bar.c $ git commit -m 'bar: fixed typo'
The important command is
git reset
, which will undo the commit. The working tree is not touched (so your modifications are still present), but the branch is rewinded and the index is reset. This means that your modifications show up again ingit diff
, for example.As shown, you can now commit the changes in as many commits as you like. Use
git add -p
to interactively add part of a file to be committed, for example. You will find the previous commit message as.git/COMMIT_EDITMSG
, so you can refer to it when making new commits.If you want to split an earlier commit
X
, you run:$ git rebase -i X^
In the line for
X
, changepick
toedit
(or juste
), save the file, and close the editor. Git will then update toX
to allow you to edit the commit. To actually split the commit, you will now use the procedure described above for splitting the last commit. That is, you run:$ git reset HEAD^
to undo the commit. Then commit the files in as many small commits as you like and finally run:
$ git rebase --continue
to finish the rebase operation.
Further reading