Making Changes

If you want to make changes to NuttX, for your own personal use, or to submit them back to project to improve NuttX, that’s easy. For the purposes of this guide, you’ll need a GitHub account, since the Apache NuttX team uses GitHub. (You could also use git locally, or save your changes to other sites like GitLab or BitBucket, but that’s beyond the scope of this guide).

Here’s how to do it:

  1. Set your git user name and email

    $ cd nuttx/
    $ git config --global user.name "Your Name"
    $ git config --global user.email "yourname@somedomaincom"
    
  2. Sign in to GitHub

    If you don’t have a GitHub account, it’s free to sign up.

  3. Fork the Project

    Visit both these links and hit the Fork button in the upper right of the page:

  4. Change the Git Remotes

    The git repositories in your project are currently connected to the official NuttX repositories, but you don’t have permission to push software there. But you can push them to your forks, and from there create Pull Requests if you want to send them to the NuttX project.

    First, remove the current remote, origin (we’ll add it back later):

    $ cd nuttx/
    $ # display the remote
    $ git remote -v
    

    You should see something like this:

    origin   https://github.com/apache/incubator-nuttx.git
    

    Now, on the GitHub web page for your forked incubator-nuttx project, copy the clone url – get it by hitting the green Clone or Download button in the upper right. Then do this:

    $ git remote rm origin
    $ git remote add origin <your forked incubator-nuttx project clone url>
    $ git remote add upstream https://github.com/apache/incubator-nuttx.git
    

    Do the same for your forked incubator-nuttx-apps project:

    $ cd ../apps
    $ git remote rm origin
    $ git remote add origin <your forked incubator-nuttx-apps project clone url>
    $ git remote add upstream https://github.com/apache/incubator-nuttx-apps.git
    
  5. Create a Local Git Branch

    Now you can create local git branches and push them to GitHub:

    $ git checkout -b test/my-new-branch
    $ git push
    

Git Workflow With an Upstream Repository

The main NuttX git repository is called an “upstream” repository - this is because it’s the main source of truth, and its changes flow downstream to people who’ve forked that repository, like us.

Working with an upstream repo is a bit more complex, but it’s worth it since you can submit fixes and features to the main NuttX repos. One of the things you need to do regularly is keep your local repo in sync with the upstream. I work with a local branch, make changes, pull new software from the upstream and merge it in, maybe doing that several times. Then when everything works, I get my branch ready to do a Pull Request. Here’s how:

  1. Fetch upstream changes and merge into my local master:

    $ git checkout master
    $ git fetch upstream
    $ git merge upstream/master
    $ git push
    
  2. Merge my local master with my local branch:

    $ git checkout my-local-branch
    $ git merge master
    $ git push
    
  3. Make changes and push them to my fork

    $ vim my-file.c
    $ git add my-file.c
    $ git commit my-file.c
    $ git push
    
  4. Repeat 1-3 as necessary

  5. Run the tools/checkpatch.sh script on your files

    When your code runs, then you’re almost ready to submit it. But first you need to check the code to ensure that it conforms to the NuttX Coding Standard. The tools/checkpatch.sh script will do that. Here’s the usage info:

    $ ./tools/checkpatch.sh -h
    USAGE: ./tools/checkpatch.sh [options] [list|-]
    
    Options:
    -h
    -c spell check with codespell(install with: pip install codespell
    -r range check only (used with -p and -g)
    -p <patch list> (default)
    -g <commit list>
    -f <file list>
    -  read standard input mainly used by git pre-commit hook as below:
       git diff --cached | ./tools/checkpatch.sh -
    

    Run it against your files and correct all the errors in the code you added, so that tools/checkpatch.sh reports no errors. Then commit the result. For example:

    $ ./tools/checkpatch.sh -f my-file.c
    arch/arm/src/sama5/hardware/my-file.c:876:82: warning: Long line found
    $ # fix errors
    $ vim my-file.c
    $ # run again
    $ ./tools/checkpatch.sh -f my-file.c
    

    If you have made a lot of changes, you can also use this bash commandline to see the errors for all the changed C files in your branch (assumes you are currently on the branch that has the changed files):

    $ git diff --name-only master | egrep "\.c|\.h" | xargs echo | xargs ./tools/checkpatch.sh -f | less
    

    Note that there are some bugs in the nxstyle program that checkpatch.sh uses, so it may report a few errors that are not actually errors. The committers will help you find these. (Or view the nxstyle Issues.)

  6. Commit the fixed files

    $ git add my-file.c
    $ git commit my-file.c
    $ git push
    

Submitting Your Changes to NuttX

Pull requests let you tell others about changes you’ve pushed to a branch in a repository on GitHub. Once a pull request is opened, you can discuss and review the potential changes with collaborators and add follow-up commits before your changes are merged into the base branch.

(from GitHub’s About pull requests page)

Before you do a Pull Request, the NuttX team will usually want all the changes you made in your branch “squashed” into a single commit, so that when they review your changes, there’s a clean view of the history. If there are changes after Pull Request review feedback, they can be separate commits. Here’s the easiest way I found to do that initial squash before submitting the Pull Request:

  1. Check out my branch

    $ git checkout my-branch
    
  2. Rename it to my-branch-old to save it, because we’re going to create new clean branch to push:

    $ git branch -m my-branch-old
    
  3. Create a new clean branch with the same name you were using before the last step:

    $ git checkout master
    $ git checkout -b my-branch
    
  4. Merge your saved old branch into the new one, telling git to “squash” all your commits into one (note this will not commit the result; the changed files will be in your staging area, ready to be committed):

    $ git merge --squash my-branch-old
    
  5. Commit the result

    $ git commit
    
  6. Force-push your new clean branch to the remote— this will overwrite all your previous changes in that branch:

    $ git push -f --set-upstream origin my-branch
    
  7. Create a GitHub Pull Request

    A Pull Request is how you ask your upstream to review and merge your changes.

    Here’s GitHub’s instructions for creating a Pull Request.


  8. Get Pull Request feedback and implement changes

    Get suggestions for improvements from reviewers, make changes, and push them to the branch. Once the reviewers are happy, they may suggest squashing and merging again to make a single commit. In this case you would repeat steps 1 through 6.