A guide for infrequent contributors to Racket

:: Racket, Git

Do the following apply to you?

  • Maybe you want to contribute something to Racket: You’d like to improve the documentation, or you’d like to add a small feature.

  • Maybe you’re comfortable with Git, but haven’t made a pull request before.

  • Maybe you’ve made a one-off pull request, but haven’t tried to contribute to the same project over time and stay in sync with the upstream project.

If so, you may find my guide helpful. I was hopelessly confused about how to handle the branches and merging. After I figured it out, I wrote this down in a Gist as a note to my future self. Today I figured I’d dust it off and make it into a blog post.

One-time fork and setup

Fork plt/racket and git clone your fork to your computer.

For more help on this, as well as building Racket locally, see Joe Gibbs Politz’s excellent blog post. Go read it now. I’ll wait.

Getting updates over time

If you haven’t already, define a remote for plt/racket:

1
git remote add upstream git://github.com/plt/racket.git

Because nobody likes a dirty fork, get updates only using this command:

1
git pull --ff-only upstream master

If you only update this way, it will ensure that your master branch is a simple, exact mirror of the plt/racket master branch.

Your master won’t become cluttered with extraneous merge commits (like “Merge branch ‘master’ of github.com:plt/racket”).

This makes it easy to create pull requests containing only the commit that you intend.

Important: The --ff-only flag is the key to this. Don’t use git pull without this flag.

Note: git pull --ff-only upstream master is a shortcut for two steps, git fetch upstream and git merge --ff-only upstream/master.

After doing:

1
git pull --ff-only upstream master

You can push this back your forked repo on GitHub:

1
git push origin master

Rebuild all after Racket version change

Eventually the Racket version number will increase and you may end up with stale compiled/ subdirectories:

1
2
3
compiled/reader_rkt.zo::0: read (compiled): wrong version for compiled code
  compiled version: 5.3.1.9
  expected version: 5.3.2.1

The usual incantation may be sufficient:

1
make && make install

To force a rebuild of all collections, also do:

1
raco setup -c && raco setup

Contributing something

Create a topic branch

Never make changes on your master branch. Instead, create a so-called “topic branch”, named after your feature:

1
git checkout -b my-feature-branch

Hack, hack, hack

Make your changes and commit.

Don’t forget tests and documentation.

Prepare your topic branch for the pull request

  1. Maybe you like to commit often as you work on a feature. I do. It’s a form of backup and a paper trail. That’s great, but preferably your pull request should be just one commit. Easier on the maintainer. Plus the upstream project doesn’t need 20 commits in its history for your 1 feature.

  2. You should rebase your topic branch on the upstream master, to catch any changes or conflicts.

You can do both with git rebase.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# First, get the latest upstream master
git checkout master
git pull --ff-only upstream master

# Rebase our topic branch on that
git checkout my-feature-branch
git rebase -i master
  # 1. In the editor, change 'pick' to 'squash' to combine
  #    multiple commits into one.
  # 2. If any conflicts from upstream, resolve them.

See squashing commits with rebase.

Push your topic branch to GitHub

To push your topic branch to GitHub:

1
git push -f origin my-feature-branch

The point of the -f (force flag) is in case you had already pushed this topic branch. After you use rebase (above), you’ll probably need to force the push.

Note: Using push -f is usually bad. Here it’s OK because we’re push -f-ing to a topic branch in our forked repo that no one has pulled from yet.

Make your pull request on GitHub

Visit your forked repo’s page on GitHub.

If you recently pushed your topic branch, you’ll see a handy button to make a pull request for the branch:

Recent pushed branch

Recent pushed branch

You can also use the main Pull Request button.

Either way, you get the Pull Request page:

Pull request page

Pull request page

The pull request page has three “tabs”:

  1. New Pull Request. This is a title and description. The title defaults to your commit message’s first line. The description defaults to the rest of your commit message. (If you have more than commit, you won’t have these defaults. But as described above, you really shouldn’t include more than one commit in your pull request.)

  2. Commits. Preferably this should have the number 1 next to it — just one commit in your pull request. You should click the tab and double-check that the commit is what you expect.

  3. Files Changed. Again, double-check to make sure it looks correct.

When all looks good, click Send Pull Request.

Waiting is the hardest part

What next? You wait for your pull request to be accepted and merged. Then it will flow back to you when you do git pull --ff-only upstream master, because your commit is now part of the official plt/racket repo.

But it might take awhile for the pull request to be accepted. It might never be accepted.

In the meantime, you might be tempted to merge your topic branch into your own master. Don’t!

If you were to do that, your master would cease being a nice clean mirror of the upstream master. Remember how no one likes a dirty fork, so we’re diligently using git pull --ff-only upstream master?

So the simplest thing to do is just wait.

But if you really want to use your feature, in your own custom build, I suggest making some other branch (e.g. custom-build). Feel free to merge from your topic branches (and from upstream master) into that branch, from which you can build your custom variation of Racket.

Just remember that topic branches for pull requests should still always be based off your master, which should be a fast-forward mirror of upstream.