Code documentation
Development Tools
Code Structure
Techniques and Standards
Help and Web Site
How To
Functional Info
Background Info

JMRI Help:

Contents Index
Glossary FAQ

Donate to JMRI.org

JMRI Code: Developing with JMRI

Background

Anybody is welcome to get a copy of the JMRI code and modify it for their own purposes. What makes one a JMRI developer is contributing those modifications back for others to use.
This page discusses how to do that, assuming that you have access to a copy of the code following this procedure.

See the JMRI Git FAQ page for more details on these processes.

The links to the left provide more information on building with specific tools. You should read the page for your particular setup.

The rest of this page provides an overview of the process of developing JMRI code with Git. Basically, you create a new branch, make your changes, compile/run/test until you've finished your intended change, and then send that change back for inclusion into the main repository.

That's done with a four-step process:

  1. You create a Git branch to hold your work.
  2. You periodically "commit" your changes to your local repository.
  3. You periodically "push" those changes to a repository of your own on GitHub.
  4. When your change is complete, you create a "pull request" that allows JMRI to get your change from your GitHub repository and merge it into JMRI's main repository.

Create a Branch for Development

Git is very good at keeping development on parallel "branches" separate. Although the primary development is on the "master" branch, we strongly recommend that you don't directly make changes to that. There are a lot of JMRI developers, and having them all work on a single branch can get confusing. Instead, you should create a separate branch for each of your projects, work on it until it's ready to be merged back into the main JMRI source, and then contribute the entire branch contents back to our main repository.

To create a new branch:

  git checkout master
git pull
git checkout -b my-new-feature-or-fix

The first two "git checkout master" & "git pull" lines makes sure that you are starting from the most recent "master" branch contents. The master branch is where we do development between test releases.

The -b option in the last line creates a new branch which will contain your new work. This lets you work on it without interference from other people's changes until you're ready to merge with those. The "checkout" means that you're now working on that new branch, which will hold whatever you commit in later steps.

Develop and Test Locally

Now that you have a copy of the code available, you can directly work in it to develop any changes you want to make. There are several different ways to do that, see the sidebar, including using Ant from the command line, using the NetBeans IDE, using the Eclipse IDE, and using the IntelliJ IDE. You use one of those to compile your code and organize it so that it can be run, and then to run both the individual programs (PanelPro, DecoderPro et al) and various tests that it's all still working.

There's not much to worry about here. If you make a bad change, you can get back the original (last changed in your checked-out branch) version with e.g.

  git checkout -- xml/decoderIndex.xml
(Note the two dashes, and change the file path to the one you want changed back) Any changes you do make aren't recorded until you commit them, see below.

There are two things you should be careful of:

As you work, we encourage you to add a brief description of your changes to the draft release note, which can be found in the help/en/releasenotes directory as the help/en/releasenotes/current-draft-note.shtml file. When your changes are eventually merged into the main repository and included in a release, this will be how other JMRI users find out about them. You can also cut&paste what you write here into your pull request (see below) to help explain your change to the people reviewing it. If your work requires that the users be warned about something, i.e. to do a migration, please also add that to the help/en/releasenotes/current-draft-warnings.shtml file which works similarly.

Commit Changes to Your Local Repository

You should commit your changes into your local repository often.

With the older SVN system, there was one central repository that everybody shared. Git provides everybody with their own local repository, and then links them together with "pull", "push" and "pull request" operations. When you commit, you're saving a copy of your changes into your local repository where they're safe, and can eventually be moved onward.

  git commit
When you do this, Git will open an editor window for your commit note. The top line becomes the summary, which should be clear by itself as this will appear in lists of changes. You should keep that summary to 50 characters or less, so it can be displayed compactly. Please add more detail in additional lines after the summary, because that helps your friends and colleagues understand what you've done.

Get Your Own GitHub Repository

This gives you your own repository, which you can then work with freely.

If you're using the command line, the next step is to connect it to your local repository. (IDE users will do this next part in their IDE, see those instructions) On the web page for your repository, right side, is a "HTTPS Clone URL". Copy that. In your repository directory on your local computer, do:

  git remote set-url --push origin https://github.com/yourname/JMRI.git
  git remote add yourname https://github.com/yourname/JMRI.git

(With the appropriate URL, changing "yourname" to your GitHub account name in three places)

After this, doing a "git push" will push your changes up to your repository. "git pull" will still pull from the main repository so that you can get the most recent updates from others. To check this, do a "git remote -v" which should show: (OK if it shows others or the order is different)

  % git remote -v
origin https://github.com/JMRI/JMRI.git (fetch)
origin https://github.com/yourname/JMRI.git (push) yourname https://github.com/yourname/JMRI.git

Push Your Changes to Your GitHub Repository

Now that you have a consistent set of changes committed locally, you can move them up to your repository on GitHub. That makes them visible to everybody else.
  git push

Possible Problems and Solutions

Sometimes, git will tell you that you need a more complicated push comment, with some options that start with - or --. Just copy and paste that line to execute it. For example, you might get an error message like:
% git push
fatal: The current branch my-branch has no upstream branch.
To push the current branch and set the remote as upstream, use

  git push --set-upstream origin my-branch
      

Just go ahead and do what it says:

  git push --set-upstream origin my-branch

And occasionally, your local repository can be out of sync with your GitHub repository. If you get a message about "failed to push some refs" or similar, without specific commands to fix it, do (the first command here is why we created that remote with your name above; make sure it's there, and substitute your GitHub name in the first line):

  git pull yourname
(If any lines are flagged as conflicts, edit those to remove the conflicts, then "git add" them to resolve the conflict)
  git commit -m "merging pull back"
  git push
It is definitely easier to do this if you have no modified files in your repository, e.g. you've committed all your local changes.

Submit a Pull Request

Once your changes are complete and ready to go, the last step is to make your changes, already visible in your GitHub repository, known to the JMRI maintainers so that one of them can pull it into the main JMRI repository. To do that, you create and submit a "pull request" that automatically has all the needed info.

Once your PR is merged, a git checkout master; git pull will bring it back around to your repository and that cycle will be complete.

While all this is happening, you can work on something else by creating another branch and making changes there. But first, pick up the most recent contents of our central repository with:

    git checkout master
    git pull
Then you can create a new branch for a new project:
    git checkout -b another-new-feature

just like you did at the start of this process, and continue to develop.

After Your Pull Request Is Merged

Once the changes in your PR has been merged onto the master branch, it will be included in the next development release built by our CI system. These packages can be downloaded and run to check that everything is working. You can also refer users to the built installers so they can test your changes.

Approximately once a month, the contents of the master branch are taken and used to build a test release. These are announced to the user community to simultaneously make new features and fixes available, and to put the most recent code into wider use to flush out problems. The build process is documented separately. People are encouraged to download and use these, then report any problems via GitHub or the jmriusers group.

Approximately twice a year, a similar process is used to build production releases.

Who are these people?

JMRI is the work of several hundred people. Anybody can contribute their work, large or small to JMRI, either by creating a PR (see above) or in other ways. You don't need any special status to create a PR and have it evaluated, just an ability to follow these instructions.

There's a group of people with "developer" status on the JMRI GitHub project who work more generally on JMRI code, for example taking on and resolving Issues opened by others. These people can assign Issues and PRs to themselves, and do a few other minor things. Typically, once somebody has solved a couple of Issues, they'll get an automated invitation to developer status from GitHub. These people are expected to be subscribed to the jmri-developers mailing list and to have public GitHub profiles that identify them.

A smaller group of JMRI "maintainers" on GitHub have the ability to edit, label and close all Issues and PRs, and to merge the contents of PRs to the main repository. This group does the infrastructure work that keeps the project code moving forward while avoiding unnecessary risk to the project's code and other assets.