Using Git
SRB2's source code is publically available in online Git repositories. The GitLab instance is where most active development takes place, and should be the repo targeted by those wishing to contribute to the game. A mirror of the source code hosted on GitHub is used to publish official releases.
Contributions in the form of Merge Requests are reviewed and accepted through GitLab.
This guide is meant to help existing programmers understand the workflow surrounding Git and GitLab and how to contribute their changes to SRB2 itself.
What is Git, a summary of the workflow
Git is a Distributed version control system that manages software's changes over time. It is used by the vast majority of new open source projects and is extremely flexible as a system, allowing parallel development by many workers and easy merging of changes through that. Distributed means that, unlike Subversion, there is no "central" repository model, and indeed every clone of a repository is a 1:1 copy of its parent, and can also act independently. The benefits of this include retaining the ability to commit without having permissions to push those commits to the origin, which is a useful model for keeping track of the changes an individual programmer makes over time.
In a Git Repo, there are one or more branches which are simply pointers to different commit HEADs. For example, the master branch (default) in a fresh clone of SRB2 will point to the very latest commit, or origin/master's HEAD. You might make an appropriately named branch and checkout it after cloning, such as fix-netcode
using the git checkout -b fix-netcode
.
For most git repo clones, you will have a working directory which pairs with the staging area. In your working directory, you will make changes in the code for your next commit. When a file is ready, you will stage it, using git add path/to/file.c
, which will put the current version of file.c
into staging. Once you've made sure everything is ready, you can commit by using the appropriately named command and a concise message, git commit -m "Make player behavior consistent across all compilers. Fixes #75"
. (Without -m, git will prompt you to enter a message, using whatever text editor is defined as default, and that's usually vim which is a whole different beast from this.) This will create a commit object named some SHA1 hex string like 0f2a8b3e8c..., and then set your current branch's HEAD, fix-netcode
, to the new commit. The new commit will have a parent of the old HEAD of fix-netcode
, which defines the family history of the entire codebase – for any commit except the initial commit, there is ancestry leading all the way back.
Once you're happy with the changes you've made and you've ensured it's clean, you might publish this branch to the public. If you have write access to the repo you cloned from, you would do something like git push origin fix-netcode
, which will automatically create the fix-netcode
branch on the "upstream" or "origin" repo, upload the necessary commit objects, and set origin/fix-netcode
's HEAD to your local branch's HEAD.
Since your code is now published, you may consider creating a merge request on GitLab to the main project. This is done on the GitLab website – you would visit STJr/SRB2, go to the Merge Requests page, create a merge request, and select your branch for merging. This opens discussion for the maintainers of STJr/SRB2 to request changes and analyze whether or not the code is suitable for a merge into next. If your code looks good and maintainers agree with the changes, they you will do a merge of that branch into next. Your code is now part of the game!
Terminology
Here is some important terminology that you should have a decent understanding of before diving into Git. In parentheses the word's linguistic uses are identified (v – verb, n – noun, etc).
- Clone (v, n). A copy of a repository with all or some history intact. You can freely traverse all commits without an Internet connection with a clone.
- Branch (v, n). A lightweight pointer to a commit, which acts as a divergence from a parent branch. Two different branches can receive commits separately, which means code history is not linear!
- Commit (v, n). The act of, or the object, that defines a set of changes a programmer has made. These usually have one parent commit, but in the case of merge commits, they will have 2 or more. Git internally uses the HEAD commit of a branch to populate your working directory by traversing up the commit history and picking out the newest versions of files available, so that the working directory exactly represents the commit that is its HEAD.
- Reset (v). The act of setting the current branch's HEAD to another commit. You'll usually do a reset if your local master branch is a number of commits behind the upstream master. This can be potentially destructive: if you have commits added to your branch that aren't in the commit you are resetting to, they WILL disappear – there are other tools meant to resolve that situation!
- Merge (v). The act of creating a new commit that "merges" all the changes of one history of commits with another. In some cases, you'll be able to do a "fast-forward" merge, if the current branch is exactly behind the target branch, which does exactly the same as a Reset. Under most circumstances, only a project maintainer should be using this.
- Rebase (v). Taking the commits that you have made on your branch, "rewinding" their changes back to a common parent on the target branch, Resetting to the HEAD of the target branch, and "replaying" your commits on top. This is a special kind of merge that forces a linear history, and because it actively creates new commits to represent the original ones, you should not use this if you have already published code.
- Working directory (n). The directory that represents all the files of the current commit or branch. You'll make your changes here.
- Staging (n). The area where copies of files from the working directory are stored until they are made into a commit object.
- Remote (n). An object which stores a push and pull address. When you use
git clone
, git automatically creates a remote calledorigin
. You'll create a few remotes to point to other people's forks, such asMonsterIestyn
pointing to MonsterIestyn's fork. - Remote branch (n). A special kind of local branch that reflects the state of a remote branch. These are not normally shown to the user but they are useful to know. They follow the name scheme
remote/branch-name
, such asorigin/master
, within your local repository. - Fetch (v). Fetching downloads the commits from a remote and stores them in your repo, setting new HEADs to your Remote Branches. You can then merge or rebase on those Remote Branches using the normal commands. Fetching also sets an alias commit name
FETCH_HEAD
that you can type in place of the nameorigin/master
, for example. - Pull (v). A combination of Fetch and Merge. Because of the merge property, it's usually recommended to Fetch first, to make sure that you will not accidentally create a new merge commit or have to deal with merge conflicts locally.
- Push (v). Pushes commits to the target, setting their new branch HEADs as necessary.
Here are some GitHub-specific terms that you should know:
- Fork (v, n). A GitLab/GitHub-side clone of a Git repo.
- Merge Request (v, n). A request to merge in some changes from a target fork to the receiver fork. Usually you would create this to merge your branch to the master branch. Each fork has their own Merge Requests.
- Issue (n). A bug report, or feature request, along with all associated discussion surrounding it. These are given a unique number. If a commit message says something along the lines of Fixes, Resolves, or Closes #XXX, GitLab will automatically close that issue when the commit is merged into
master
! Each fork has their own Issues repo.
Cloning and using the code
The code is hosted at STJr/SRB2. In order to get a useful copy of it, you will have to clone it using a Git client.
If you plan to contribute to the source code on Windows, the recommended route is to install MSYS2 as you will also need it for compiling and testing your changes. See the steps to install MSYS2.
Otherwise, follow the instructions for your operating system here.
Before cloning the code, you'll want to create your own fork on GitLab of it. Create an account on GitLab, go to the STJr/SRB2 GitLab project page, and click the Fork button in the top right. You'll have a copy of the repo made on your GitLab account, which you will have write access to. That is the fork you'll want to clone from! Otherwise you will not be able to publish your changes.
If you cannot fork the repo, ping @git-admin on discord. Your account may need its project limit raised.
Use your client to clone the repo. On command line, it's this:
$ git clone https://[email protected]/username/SRB2.git
At this point, you may also want to create a new remote to point to STJr/SRB2:
$ git remote add stjr https://git.do.srb2.org/STJr/SRB2.git
Be sure to run this command often to refresh changes on the remote side, as it does not automatically update:
$ git remote update
Common workflows
Below are some common workflows that you may reference to when you need a little reminder on how things work.
Contributing your changes in STJr/SRB2
- Get an idea for what you want to fix or improve. Have a plan ready. Know fairly well what you want to do with the code!
- Create fork and pull it (if needed)
- Add a remote to STJr to rebase or reset in case STJr changes (if needed)
- Create branch.
git checkout -b simple-name-describing-topic
- Checkout your new branch (using checkout -b instead of branch does this automatically. useful tip!)
- Code and commit
- When ready to publish, push to origin branch.
git push origin simple-name-describing-topic
- When ready to submit, create a merge request. (Do this on GitLab)
- Name concise, then give a good description about the changes. "Topic to add new functions for Lua"
- Indicate which Issues this fixes ("fixes #36")
- Discussion opens on your changes
- Continue committing and pushing as adjustments are requested/you find other relevant changes
- Pull request is merged? Delete your branch locally and remotely to clean things up.
git checkout master; git branch -d simple-name-describing-topic
- Update next to stjr/next. Press the "update fork" button on your GitLab next branch, then
git remote update
andgit pull