Guide to working with tgstation as an upstream repository

Foreword

Sorry about the long-winded title. I'm guess I'm not very good at naming things. Nullquery (talk) 19:56, 14 January 2016 (UTC)

The information in this article will provide you with the knowledge you need to run and maintain your own "flavor" of /tg/station while retaining the ability to remain up-to-date with the latest bugs features that the /tg/station developers have to offer.

Accepting your fate

The first step is accepting your fate, namely that you will never be able to make changes to the main /tg/station source-code without getting merge conflicts, and therefore headaches. If you want to do this you'll have to change your attitude.

When you first check out your repository create a folder for your version. For example, I named mine "_nullstation". The underscore is so the folder appears at the top in sorted file listings.

All code and icons you don't share with /tg/ go in that folder. You shouldn't do anything outside that folder (apart from some exceptions listed below) to prevent conflicts between files. You DON'T want want to end up thousands of commits behind and unable to update without spending weeks sorting through all the changes. And since they tend to commit stuff all the time you WILL get out-of-date. My advice is to merge with upstream often to ensure you have the latest changes and don't suddenly have to rewrite all of your custom changes because the entire API's changed. Remember, the people you're dealing with go through UI managers on a bi-quarterly basis. If they're that uncertain about a freaking browser encapsulation problem then expect any and all API's to change at any time.

Contribute as much as possible

I'm not an official member of the /tg/station development team but it's safe to say that if they've accepted my pull requests that they're pretty lenient on what's added so long as it doesn't break things or introduce a bad habit to the codebase. So far they've been willing to play ball and discuss things, though don't expect your pull request to be accepted even if you do everything right because the people in charge _will_ nitpick your changes and _will_ have conflicting opinions about how things need to be done.

I know. Why bother with this at all, right? Well, they are keen to fix bugs and improve the overall game, and unless you've got as much of a backing as they do you're not going to stand a chance.

A brief primer on Git terminology

The main difference between Git and other version control systems is that Git stores the repository on your local computer where other repositories would have them on a central server.

You *commit* your changes to your *local* repository. You then *push* those changes to a *remote* repository.

  • Local* is your own computer. *Remote* is a remote server. *Origin* refers to the repository you're likely to push to (your original repository, before you made a local one). *Upstream* refers to your lord and masters, the parent repository which you inherit from.

In the examples below the local repository resides in a folder on your computer, the origin repository is a forked repository on Github that you own, and the upstream repository is the main /tg/station repository.

A *fork* is a copy of another project, potentially with changes. A fork starts off as a duplicate of another project, but may change over time. There are some "forks" of SS13 that have changed so heavily that they're no longer part of the project they forked from, though (for licensing purposes) keep in mind that they did initially start out as a duplicate of the original project.

Now we move on to the tree analogy. A Git repository is like a tree. A tree has branches. A *branch* is a single copy of the source-code. Different branches may have different changes. One may be an entire rewrite of the atmospherics system. Another may be the same game but with only minor map modifications. The *master branch* is your default branch, your initial position within the tree.

Setting up your project in a few easy steps

  1. If you're not comfortable with Git and running on Windows then I advise to get the TortoiseGit program. It encapsulates a lot of commands in easy-to-use buttons and wizards. When in doubt, bug oranges, tkdrg, Mloc or nullquery on IRC (in that order). This guide assumes you're using TortoiseGit.
  2. Fork from the main /tg/station Github repository. Go to https://github.com/tgstation/-tg-station and hit the "Fork" button.
  3. You can now check out the repository. To clone a repository:
    1. Copy the Git URL from your repository
    2. Create a new folder on your system for your projects (e.x., "My Documents\Projects")
    3. Right-click your new folder. Then click "Git Clone..."
    4. The URL should already be visible on a textbox near the top. Just click 'ok' to continue.
  4. A new folder will have been created, e.x. "My Documents\Projects\-tg-station"
  5. Rename the "-tg-station" folder to "tgstation". If you don't, running the .dmb directly will run it in ultrasafe mode which will prevent it from reading/writing its own files.
  6. This next step is very important. Create a new branch for your version. Do this by right-clicking the "tgstation" folder and under the menu option "TortoiseGit" click "Create Branch..."
  7. You will now have to provide a name for your branch. In my case I named it "ns-master" (shorthand for "nullstation-master"). It doesn't matter what the name is, so long as you're comfortable with it. Note that the standard is to have "master" in the name if it's your main branch. Make sure to tick "Switch to new branch".
  8. If you forgot to tick "Switch to new branch": right-click the folder, under the "TortoiseGit" menu option search for "Switch/Checkout..." to change to a different branch.
  9. We'll now push the repository to Github, which will create your branch online. Right-click the folder and click "Git Sync...".
  10. Set the remote branch to the same name as your branch (you can manually type in the name) and click "Push...". You will now have to provide your login credentials for Github.
  11. Head over to your repository on Github and confirm that the branch is listed under the list of branches. (The list of branches is the dropdown that says "Branch: master").
  12. Click the "Branches" tab. Click "Change default branch" and specify your own "master" branch as the default.

You now have the basics set up. In order to commit and push your changes to Github:

  1. Make changes to the project. I.e., add a new file, modify a file, delete files.
  2. Right-click the main project folder (the "tgstation" folder) and click "Git Commit..." (the actual name will vary as it will contain the name of the local branch you're committing to)
  3. Be sure to tick any files that you do want to include and untick any files you don't want to include.
  4. Type in a message explaining what you changed. This is important if you intend to push your changes to the main /tg/station repository as they'll want a short description of what you did. It's also helpful for you to know, and for the commit logs.
  5. Click "OK" to commit.

Note that this will only commit changes to your local computer. To push your changes to Github:

  1. Right-click the main project folder and click "Git Sync..."
  2. Click "Pull" to ensure you're up-to-date with any changes from the remote server.
  3. Click "Push" to push your changes. It will ask for your credentials to authorize this action.

Contributing to /tg/station

While plenty of articles offer more detail into this process, note that Github handles this part, so there's virtually no knowledge of Git required to create a pull request.

Topic branches

One thing to note is what is called "topic branches". I've previously explained what a branch is in the Git terminology section. From a technical point-of-view a "topic branch" is no different than a regular branch. The reason they're called "topic branches" is because the branch is intended to handle a particular topic, such as a bug fix or implementing a feature.

The point of splitting everything you do up into branches is to make it easy to submit multiple pull requests to other repositories for each change. If you made all of your changes under the default branch then there is no way to differentiate between your changes when you submit your pull request. Pull requests always submit every change in an entire branch, there's no way to exclude specific commits.

Rebase, or: how to update from /tg/station without losing your modifications

Rebase in a nutshell: start over from the current state of the /tg/station repository, then reapply all of your changes one-by-one. Except instead of doing it manually and losing a lot of time, the process is automated.

In order to perform a rebase for the first time do the following:

  1. Make sure you have no modifications that you still have to commit, because you'll lose them.
  2. Right-click your main project folder and click "Git Bash". This will give you a command prompt where you can type Git commands directly.
  3. Type "git remote -v" and check if you have an "upstream" remote listed.

Assuming you have done so, use the following commands every time you want to update:

  1. Type "git fetch upstream" to fetch all the changes from /tg/station.
  2. Type "git rebase upstream/master" to re-apply your modifications. This will fail if there are conflicts. In that case, type "git rebase upstream/master --continue" after you've resolved the conflict.

Frequency asked questions

I'm leaving this section open for anyone who has any questions. Feel free to add them, and maybe when someone knowledgeable looks at this page they'll update this section with an answer.

Why don't you use submodules?
Submodules work by storing the hash of a particular commit in the repository you're working on. This will work. It'll work great, and it'll never fail... assuming you work alone. If you don't, someone else will invariably commit the submodule with the wrong hash and cause it to point to either an outdated or newer version. Then you'll have to undo those changes again.
Another reason is that while they remove a lot of ballast it becomes impossible to make changes to any files within the submodule without committing those. The only way out is to fork the /tg/station repository, but if you're going to do that then you may as well use the rebase method to remain up-to-date.