Skip to content
Tobias Blomberg edited this page Oct 25, 2015 · 7 revisions

Contributing code

Code contributions are welcome. Just make sure to follow the instructions on this page in detail. Any deviation from the instructions mean more job for me or if it’s really bad the contribution will not be accepted until fixed.

One mistake open source contributers do is to confuse "contribution" with "help". Not all contributions actually help since there very often is a fair amount of work to go through a patch. If the contribution is of low priority for the project maintainer, expect the process to take a lot of time.

All new features should be developed using the latest code from Git. The forking workflow should be used on GitHub to contribute to the project.

GitHub preparations

To be able to contribute you must have a GitHub account. Head over to GitHub to create an account if you don’t already have one.

Then you need to configure git locally on your system. The documentation at GitHub says it all so there is no meaning in repeating it here

The forking workflow

The first step in contributing to SvxLink is to create a fork of the SvxLink Git repository. Creating a fork means that you get your own repository of SvxLink that is connected to your GitHub user account.

Clone your fork

Next clone your fork. Cloning in Git will get you a local copy of the repository on your harddrive.

$ git clone [email protected]:USERNAME/svxlink.git
Cloning into 'svxlink'...
remote: Reusing existing pack: 20471, done.
remote: Total 20471 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (20471/20471), 4.69 MiB | 745.00 KiB/s, done.
Resolving deltas: 100% (13624/13624), done.
Checking connectivity... done.
$ cd svxlink

The new clone will be associated with your fork on GitHub. This is called the origin.

Associate your clone with the official repository

We will also need to associate the clone with the original SvxLink repository. That is called the upstream repository.

git remote add upstream https://github.com/sm0svx/svxlink.git

Create a feature branch

The main branch in Git is called "master". Never change anything without first creating a branch. Contributions directly from the master branch will not be accepted. Also, never use a branch to implement more than one feature. A branch that contains multiple feature changes will not be accepted into the SvxLink core distribution.

$ git checkout -b my_new_feature master
Switched to a new branch 'my_new_feature'

You can verify that you are on the correct branch using the following command.

$ git branch
  master
* my_new_feature

To get the status of the whole tree, use:

$ git status
On branch my_new_feature
nothing to commit, working directory clean

Implement the feature

Now you can start developing the new feature. Committing changes in Git is a two step process. First both new and changed files will have to be added to something called the index, or staging area. It’s the files added to the index that will later be committed. In this example the INSTALL file has been changed and a README file has been added. Using the status command will look like this:

$ git status
On branch my_new_feature
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   INSTALL

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        README

no changes added to commit (use "git add" and/or "git commit -a")

Let’s say we want to commit both these files. We then use the add command:

$ git add INSTALL README

Now the status will look like this:

$ git status
On branch my_new_feature
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   INSTALL
        new file:   README

Before committing it’s always good to check what we are actually going to commit. That can be done using the git diff command. The "--cached" command line argument will tell git to do the diff against the staged files that we added above.

$ git diff --cached
diff --git a/INSTALL b/INSTALL
index f06d5fc..a2c38e5 100644
--- a/INSTALL
+++ b/INSTALL
@@ -42,3 +42,5 @@ command line switch are:

 For more detailed information, see http://www.svxlink.org/

+Added some information to the INSTALL file...
+
diff --git a/README b/README
new file mode 100644
index 0000000..92e04e7
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+This is a shiny new README file.

If everything looks good we can now commit the changes. Make sure to write a good comment that properly describe what has been changed.

$ git commit
[my_new_feature ffdd69b] Added some information to the INSTALL and README files
 2 files changed, 3 insertions(+)
 create mode 100644 README

The commit message should be formatted like the example below.

Short (50 chars or less) summary of changes

More detailed explanatory text, if necessary.  Wrap it to
about 72 characters or so.  In some contexts, the first
line is treated as the subject of an email and the rest of
the text as the body.  The blank line separating the
summary from the body is critical (unless you omit the body
entirely); tools like rebase can get confused if you run
the two together.

Further paragraphs come after blank lines.

  - Bullet points are okay, too

  - Typically a hyphen or asterisk is used for the bullet,
    preceded by a single space, with blank lines in
    between, but conventions vary here

Push the feature branch to your fork on GitHub

Your changes are only committed locally right now. Nothing has been sent to GitHub yet. Before pushing the branch for the first time, commits can be changed or removed if needed. Also it’s possible to discard the whole branch if it did not turn out to be useful and no trace will be left of it.

To publish this branch on GitHub, use the following command the first time:

$ git push -u origin my_new_feature
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 406 bytes | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)
To [email protected]:USERNAME/svxlink
 * [new branch]      my_new_feature -> my_new_feature
Branch my_new_feature set up to track remote branch my_new_feature from origin.

On the following pushes, just use:

$ git push
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 370 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To [email protected]:USERNAME/svxlink
   671b23a..8b3c43a  my_new_feature -> my_new_feature

After a commit has been pushed to GitHub it must not be changed. That will cause confusion for other users possibly using your repository. It is possible to do but should be done with great care after reading all the proper documentation so that all side-effects are well understood. It is of course ok to add new commits but just don’t change already existing ones.

Create a pull request

Before creating a pull request, inspect the diff so that you are really sure of what you are going to submit. Make sure that you have not changed anything unintentionally.

$ git fetch upstream
$ git diff upstream/master..
Note
If you believe that the upstream master branch has changed since you created your task branch, first do a merge as described in Work on the pull request. A typical sign of that the master branch have changed is that you see deleted code in the diff that you know you did not delete. The diff tool will see that the newly added code in the master branch is missing from your branch so it assumes you have deleted it.

A common problem is that the editor has automatically stripped away trailing spaces. Even if this normally is a good thing to do it can cause chaos when later trying to do a merge. Two branches that would not normally conflict can have a lot of conflicts due to the changes in whitespace. Also it is very hard to inspect a patch if most of the changes are whitespace changes. The real changes will get lost in the "noise".

Another case where unintentional changes may slip into a branch is if the master branch has been modified in your own fork of the main repository. Never do ANY changes in your own master branch. It should be an exact copy of the upstream master branch.

When you are done with your branch and want to contribute it back to the SvxLink main distribution, go to the GitHub web page for your repository. There you will find your recently pushed branches and a button next to it saying "Compare & pull request". Push that button to start creating a pull request. Enter detailed information describing the changes. A notification will now be sent to the original repository owner.

Work on the pull request

Changes can be discussed in the pull request (PR). Changes can be done to the branch until its quality is satisfactory.

If a branch live for a long time it will deviate from the master branch. The bigger the deviation, the harder it will be to merge. This is a good reason to keep branches up-to-date with the master branch. There are a couple of ways of doing that, rebase and merge. Rebase should not be used if a branch has already been pushed to GitHub so merge is the safe thing to do. The following commands will update your branch with the latest changes from upstream/master.

Note
Make sure that you have set up the 'upstream' remote as described above before continuing.
$ git fetch upstream
$ git merge upstream/master
$ git push

If it’s a more complicated patch that need to be worked on by both the SvxLink maintainer and the original contributor, a few more steps need to be done to keep the branches synchronized. The SvxLink maintainer will typically create a branch in the official repository called 'your_username-my_new_feature'. Keeping in synch is easy:

git fetch upstream
git merge upstream/your_username-my_new_feature
git push

Finishing up

When the patch has reached acceptable quality, the SvxLink maintainer can merge the branch into the main SvxLink distribution master branch. When the PR has been accepted and fully merged, pull the changes from the original SvxLink repository and push it to your own master on GitHub.

$ git checkout master
Switched to branch 'master'
$ git fetch upstream
$ git merge upstream/master
$ git push

Clean up

If it looks good, the branch can now be deleted. That have to be done both on GitHub and locally. On GitHub there is a button to press at the end of the PR. Locally, delete the branch using the following command:

$ git branch -d my_new_feature
Deleted branch my_new_feature (was ce2b61e).

Also read the documentation on GitHub for how to contribute to a project.

Coding Guidelines

Here are some guidelines for contributing code to SvxLink. If these are not followed it will take me longer to accept the patch and if it’s really bad it will be rejected all together.

  • Before putting in a lot of time to code a feature, send an e-mail to the svxlink-devel mailing list to see if someone else is working on something similar and that what you are about to do is in compliance with the architecture in SvxLink.

  • Stick to the coding standards. Just look at existing code and do the same. Examples:

    • Never ever change the TAB size in your editor. It should always be eight characters wide.

    • Indentation should be two spaces.

    • No single line of code should exceed 80 characters unless it is impossible to break it up.

    • Variables are always in small caps. Words should be separated using underscore (e.g. my_variable)

    • Member variables may be prefixed with "m_" to distinguish them from other variables (e.g. m_my_member_variable).

    • Type and class definitions are written in upper camel case (e.g. MyClass)

    • Member and class functions are written in lower camel case (e.g. myFunction)

    • Macros and static constants are written in all upper case (e.g. MY_CONSTANT)

  • Update the appropriate manual page if you have added a new feature.

  • Try to keep branches as clean as possible. One branch should contain one new feature, if possible. Try to avoid lumping a lot of new features into one "personal" branch. The risk here is that the branch will grow larger while new features are added but not finished. Creating separate branches for each feature will encourage finishing implementing a feature so that it can be merged to git master and then merged into other branches that need it.

  • You are responsible for keeping your branches in sync with git master. This is to make later merging easier and of course so that you get the latest features into the branches. It’s pretty easy to do as well unless lots of changes conflict. Then it can be a bit of a pain. This should not be a big problem unless we start to have a lot of overlapping features being developed at the same time.

  • All checkins should have a meaningful comment. This is very important. The checkin comment will be shown on the "GitHub Commits" page so it serves as information to other users of what is going on. It is also very important to have a good comment if one want to go back to check when something specific was changed. Maybe a bug was introduced at some point. It will be easier to find if a good comment is used.

  • Try to check stuff in together that belong together in one go. Don’t check it in file by file.

  • Don’t check multiple changes in together that don’t directly belong together. One may later want to remove something that was checked in earlier. That will be much harder if multiple unrelated changes are lumped in the same commit.

Clone this wiki locally