Pull request workflow¶
The so-called "PR workflow" used by Godot is common to many projects using Git, and should be familiar to veteran free software contributors. The idea is that only a small number (if any) commit directly to the master branch. Instead, contributors fork the project (i.e. create a copy of it, which they can modify as they wish), and then use the GitHub interface to request a pull from one of their fork's branches to one branch of the original (often named upstream) repository.
The resulting pull request (PR) can then be reviewed by other contributors, which might approve it, reject it, or most often request that modifications be done. Once approved, the PR can then be merged by one of the core developers, and its commit(s) will become part of the target branch (usually the master branch).
We will go together through an example to show the typical workflow and associated Git commands. But first, let's have a quick look at the organization of Godot's Git repository.
Git source repository¶
The repository on GitHub is a Git code repository together with an embedded issue tracker and PR system.
Note
If you are contributing to the documentation, its repository can be found here.
The Git version control system is the tool used to keep track of successive edits to the source code - to contribute efficiently to Godot, learning the basics of the Git command line is highly recommended. There exist some graphical interfaces for Git, but they usually encourage users to take bad habits regarding the Git and PR workflow, and we therefore recommend not to use them. In particular, we advise not to use GitHub's online editor for code contributions (although it's tolerated for small fixes or documentation changes) as it enforces one commit per file and per modification, which quickly leads to PRs with an unreadable Git history (especially after peer review).
See also
The first sections of Git's "Book" are a good introduction to the tool's philosophy and the various commands you need to master in your daily workflow. You can read them online on the Git SCM website. You can also try out GitHub's interactive guide.
The branches on the Git repository are organized as follows:
The
master
branch is where the development of the next major version occurs. As a development branch, it can be unstable and is not meant for use in production. This is where PRs should be done in priority.The stable branches are named after their version, e.g.
3.1
and2.1
. They are used to backport bugfixes and enhancements from themaster
branch to the currently maintained stable release (e.g. 3.1.2 or 2.1.6). As a rule of thumb, the last stable branch is maintained until the next minor version (e.g. the3.0
branch was maintained until the release of Godot 3.1). If you want to make PRs against a maintained stable branch, please check first if your changes are also relevant for themaster
branch, and if so make the PR for themaster
branch in priority. Release managers can then cherry-pick the fix to a stable branch if relevant.There might occasionally be feature branches, usually meant to be merged into the
master
branch at some time.
Forking and cloning¶
The first step is to fork the godotengine/godot repository on GitHub. To do so, you will need to have a GitHub account and to be logged in. In the top right corner of the repository's GitHub page, you should see the "Fork" button as shown below:
Click it, and after a while you should be redirected to your own fork of the Godot repo, with your GitHub username as namespace:
You can then clone your fork, i.e. create a local copy of the online repository (in Git speak, the origin remote). If you haven't already, download Git from its website if you're using Windows or macOS, or install it through your package manager if you're using Linux.
Note
If you are on Windows, open Git Bash to type commands. macOS and Linux users can use their respective terminals.
To clone your fork from GitHub, use the following command:
$ git clone https://github.com/USERNAME/godot
Note
In our examples, the "$" character denotes the command line prompt on typical UNIX shells. It is not part of the command and should not be typed.
After a little while, you should have a godot
directory in your current
working directory. Move into it using the cd
command:
$ cd godot
We will start by setting up a reference to the original repository that we forked:
$ git remote add upstream https://github.com/godotengine/godot
$ git fetch upstream
This will create a reference named upstream
pointing to the original
godotengine/godot
repository. This will be useful when you want to pull new
commits from its master
branch to update your fork. You have another
remote reference named origin
, which points to your fork (USERNAME/godot
).
You only need to do the above steps once, as long as you keep that local
godot
folder (which you can move around if you want, the relevant
metadata is hidden in its .git
subfolder).
Note
Branch it, pull it, code it, stage it, commit, push it, rebase it... technologic.
This bad take on Daft Punk's Technologic shows the general conception Git beginners have of its workflow: lots of strange commands to learn by copy and paste, hoping they will work as expected. And that's actually not a bad way to learn, as long as you're curious and don't hesitate to question your search engine when lost, so we will give you the basic commands to know when working in Git.
In the following, we will assume as an example that you want to implement a feature in
Godot's Project Manager, which is coded in the editor/project_manager.cpp
file.
Branching¶
By default, the git clone
should have put you on the master
branch of
your fork (origin
). To start your own feature development, we will create
a feature branch:
# Create the branch based on the current branch (master)
$ git branch better-project-manager
# Change the current branch to the new one
$ git checkout better-project-manager
This command is equivalent:
# Change the current branch to a new named one, based on the current branch
$ git checkout -b better-project-manager
If you want to go back to the master
branch, you'd use:
$ git checkout master
You can see which branch you are currently on with the git branch
command:
$ git branch
2.1
* better-project-manager
master
Be sure to always go back to the master
branch before creating a new branch,
as your current branch will be used as the base for the new one. Alternatively,
you can specify a custom base branch after the new branch's name:
$ git checkout -b my-new-feature master
Updating your branch¶
This would not be needed the first time (just after you forked the upstream
repository). However, the next time you want to work on something, you will
notice that your fork's master
is several commits behind the upstream
master
branch: pull requests from other contributors would have been merged
in the meantime.
To ensure there won't be conflicts between the feature you develop and the
current upstream master
branch, you will have to update your branch by
pulling the upstream branch.
$ git pull --rebase upstream master
The --rebase
argument will ensure that any local changes that you committed
will be re-applied on top of the pulled branch, which is usually what we want
in our PR workflow. This way, when you open a pull request, your own commits will
be the only difference with the upstream master
branch.
While rebasing, conflicts may arise if your commits modified code that has been
changed in the upstream branch in the meantime. If that happens, Git will stop at
the conflicting commit and will ask you to resolve the conflicts. You can do so
with any text editor, then stage the changes (more on that later), and proceed with
git rebase --continue
. Repeat the operation if later commits have conflicts too,
until the rebase operation completes.
If you're unsure about what is going on during a rebase and you panic (no worry,
we all do the first few times), you can abort the rebase with git rebase --abort
.
You will then be back to the original state of your branch before calling
git pull --rebase
.
Note
If you omit the --rebase
argument, you will instead create a merge
commit which tells Git what to make of the two distinct branches. If any
conflicts arise, they would be resolved all at once via this merge commit.
While this is a valid workflow and the default behavior of git pull
,
merge commits within PRs are frowned upon in our PR workflow. We only use
them when merging PRs into the upstream branch.
The philosophy is that a PR should represent the final stage of the changes made to the codebase, and we are not interested in mistakes and fixes that would have been done in intermediate stages before merging. Git gives us great tools to "rewrite the history" and make it as if we got things right the first time, and we're happy to use it to ensure that changes are easy to review and understand long after they have been merged.
If you have already created a merge commit without using re