Git Workflow

Contents of this page:

Full details
Forking Workflow

Other interesting reading:

Quick Summary

Each developer should fork the core Ghost repo into a repo of their own and clone this as their local repo. Remember to add the main repo as a remote:

git remote add upstream

The main repository's master branch always contains the latest changes. For more info on branches, see the branching strategy notes.

Changes should adhere to our coding standards, commit messages should follow our notes below, and pull requests should be submitted as per the guidelines.

Notes on writing good commit messages

Commit Messages
  • The first line of your commit message should be a short (80 chars) public description of what you have achieved with the commit. This is important because it's what appears in the Ghost change log.
  • Leave a blank line after the first line.
  • The 3rd line should reference the issue with issue #000 if you just want to mention an issue or closes #000 if your commit closes an issue. If you don't have an issue to reference or close, think carefully about whether you need to raise one before opening a PR.
  • Use bullet points on the following lines to explain what your changes achieve and in particular why you've used your approach.


Show message and don't start on unsupported node versions

closes #292
- added engines and enginestrict properties to package.json
- these provide warnings / errors when installing through npm
- added our own check using this info on start, throws a useful error and stops the app if the node version is not supported
- also switched sqlite3 to the latest version and checked it works with various node versions

See the original.

If you need to update your existing commit message, you can do this by running git commit --amend on your branch.

Submitting Pull Requests

The easier it is for us to merge a PR, the faster we'll be able to do it. Please take steps to make merging easy and keep the history clean and useful.

Always work on a branch. It will make your life much easier, really. Not touching the master branch will also simplify keeping your fork up-to-date.

Use issues properly. We have a whole set of guidelines on how to raise an issue. Bugs, changes and features are all different and should be treated differently. Use your commit message to close or reference issues. The more information you provide, the more likely your PR will get merged.

Note: If you are not comfortable with git rebase, make a special 'merge' branch of your branch to do these things on, then if something goes awry you can always go back to your working branch and try again.

Clean-up history

Whilst you're working on your branch on your own, you can do all the commits you like - lots of little commits are highly recommended. However, when you come to submit a PR, you should clean your history ready for public consumption.

  • Run git log --oneline master..your-branch-name | wc -l to see how many commits there are on your branch.
  • Run git rebase -i HEAD~# where # is the number of commits you have done on your branch.

Use the interactive rebase to edit your history. Unless you have good reason to keep more than one commit, it is best to mark the first commit with 'r' (reword) and the others with 's' (squash). This lets you keep the first commit only, but change the message.

Your commit message(s) should follow the pattern described in the notes above. The first line of your commit message will appear in the change log which goes out to our VIPs with each pre-release, so please keep that in mind.

Check it passes the tests

Run grunt validate to check that your work passes jshint/jscs linting and the tests. If this fails, your PR will throw an error when submitted.


Now that your history is nice and clean, fetch the latest updates from upstream. Assuming you haven't changed the master branch, do:

> git checkout master
> git pull upstream master

Then rebase your branch/changes on top of master:

> git checkout my-branch-name
> git rebase master

And finally push your work to your fork:

> git push -u origin my-branch-name

GitHub will offer to create a pull-request from newly created branches automatically.

Now submit your PR with all the latest changes from master and a nice clean history with useful commit messages. Finish up by adding a description to the PR which details any interesting changes, any tools or libraries you've added and warnings for any breaking changes.

Updating a Pull Request

If your PR has fallen behind the master branch and can't be merged cleanly, just re-do the steps above (pull from master, rebase your branch), then force push to your branch using git push -f origin my-feature-branch. This will update the PR commits. Of course, never force push to any branch you have shared with others & be very careful about what you force push.

Fixing up Code Style / Tests

If you've made a PR that needs a quick fix for code style or tests, the easiest way to do this and end up with a single commit is:

  • make your changes
  • use git add to stage your changes
  • run git commit --amend to add these changes to your existing commit
  • then force push to your branch using git push -f origin my-feature-branch

Note: - this is my (@ErisDS') way of getting everything neat and tidy, you may have another, as long as the result is nice easy-to-merge PRs.

What Happens Next

Firstly, we will give your code a read through. Small changes usually get merged as soon as we've had chance to read through them. For more involved changes one of us will checkout your PR, rebase with master if required and then run basic sanity / regression tests on the code, run the casper tests and re-run grunt validate. If your PR has fallen behind master and can no longer be merged, we will in most cases rebase / merge master. In some cases with lots of small changes we will ask you to do this as you are more familiar with your changes than we will be.

Working with issues

Feel free to pick up any issue which is not assigned. Please leave a comment on the issue to say you wish to pick it up, and it will get assigned to you.

Branching Strategy

master on the main repository always contains the latest changes. This means that it is WIP for the next minor version and should NOT be considered stable.

Stable versions are tagged using semantic versioning.

On your local repository, you should always work on a branch to make keeping up-to-date and submitting pull requests easier, but in most cases you should submit your pull requests to master. Where necessary, for example if multiple people are contributing on a large feature, or if a feature requires a database change, we make use of feature branches. If you are working on something which you feel needs to go into a feature branch, let Hannah know and she will create this for you.

Release Procedure

Each release has an associated milestone in GitHub, against which issues are assigned. There are usually issues for each milestone feature, plus other bug fixes and enhancements that we would like to get done.

Each Milestone has a due date. This date is usually a Monday, for example for 0.5 this is Monday 31st March. The due date is the last day on which PRs can be submitted for the milestone. Once we get to the end of the due date, any new PRs will not be considered.

The following Tuesday and Wednesday will be used to merge all PRs which made it into the release and are ready, and for testing the whole package.

On the Thursday, the release candidate .zip will be generated and made available. We will ask that it be tested by as many people as possible! There will be 4 days (inc weekend) for testing.

Finally, on the following Tuesday, if all has gone well, we will provide the release zip as the new download on, and add it to the releases on GitHub.

Database Changes

Database changes require quite a bit of work around migration, exports and imports. As it stands, we currently always deliver database changes along with a minor version bump. Therefore it is important that all database changes are made on a branch so that they can be merged at a time when version bumping is convenient.

Navigating GitHub

Ghost's GitHub is full of useful information if you know how to find it, this page is a quick guide to the conventions and hidden stuff you'll find.


In addition to the Branching Strategy documented above, you may find the following branches:

gh-pages - this branch contains all of the code and content for This is open to contributions.

###-data-updates - a branch starting with 3 numbers is probably to do with schema changes that require us to bump the database version number.

Open Issues

Open issues on GitHub are a combination of things we're actively working on, or will be working on soon, and bugs. Our contributing guidelines contain lots of information about raising an issue.

Some issues start with [Discussion] which means there is no active work to be done, we're just deciding what to do or how to do something.

Others start with [Draft] indicating the issue is a placeholder for some work we know we need to do, but we aren't 100% sure what it looks like yet.

You may also see [Investigation] which is our equivalent of a spike. It usually means that the work to be done does not require a PR, but rather some testing or learning around how a particular approach might solve a problem.

Pull Requests

Pull requests (PRs) for Ghost tend to fall into a few loose categories:

  • Works in progress - something that is partly finished, or may have a problem and hasn't been worked on in a while. These are marked with [WIP].
  • Everything else is a standard PR waiting to be merged.


Ghost tries to use labels to indicate what aspect of the code base an issue belongs to, and we try to avoid workflow labels. We do have a [TOP PRIORITY] label that is used to indicate when an issue is required to close a milestone, and a [QA] label to tell QA engineers about any issues which require particular testing attention.

[epic] issues are intended for managing groups of issues. They are not a unit of work, but rather used for managing smaller projects within a milestone.

We also have a special label [beginner] which is used to indicate that an issue may be good for people who are new to the Ghost code base (as opposed to new to development), this is to help new contributors get their first commit :)

The [client] and [server] labels are intended to show which 'side' of the code base an issue belongs, with client issues referring to the ember app, and server issues referring to serving blogs, or core functions like middleware.

The [api] label refers to the JSON data api

The [data] label refers to anything in the models or schema - the data layer underneath the api.

[importer] is a project-specific label intended for the 0.5 milestone only

All the other labels should be self-explanatory.

Git Workflow