Skip to content

How to use Git

Cheese edited this page Apr 12, 2017 · 1 revision

Git is a distributed source control system, which keeps track of all changes made to files within a "repository", and provides tools for navigating these histories and merging with changes from others.

If you haven't used Git before, please take the time to learn how to use it. This page is not a full tutorial, but it will point you to the right direction. If you do have past experience with git, it's still a good idea to check out our best practices. This is pretty standard stuff, but try make sure you are aligned with it.

Table of Contents

Getting started

There are much better guides on how to work with Git than this one. Probably one of the best ones to get started with is this guide in Stack Overflow.

Quick tip: don't feel overwhelmed!* It takes a bit of practice to get the hang of it. A lot of the examples are command line interface, but most commands are fairly simple. You may find some useful GUI frontends (such as Git Tortoise or the GitHub app for Windows and Mac), but it's better if you know your basic command lines. Regardless to the way you run Git, you must learn the basic concepts and best practices. When you feel lost or insecure, just ask!

See this github help page for some details of what's being discussed in this part.

Forking

Since you want to contribute to this project, you don't create your own repository. Instead you should fork the current repository. Forking a repository means you have your own copy. Unlike your file system in which you copy a file and it's completely separate, forking means you can still get updates from the main repository and still contribute changes you make in your forked repository back to the main repository.

In github it's rather simple to fork, just click on the button and a forked repository will appear for your github user. github forking

Cloning

We are pretty much done with the github web interface for now, so get comfortable. The next step is to clone your forked repository to your local machine. Cloning is actually just like forking, but in this case you will be using git. Go to the parent directory where you'd like to clone your repository.

$ git clone https://github.com/<username>/pongball.git

Where is your github user name. This command will create a subdirectory called pongball and copy all the files in the repository.

Setting up Remotes

So now you have 2 of your cloned repositories. The first is the github fork and the second is your local clone. When you cloned the repository git automatically added a remote called 'origin'. Whenever you commit your changes to git it saves them only locally. If you would like to update your changes to your forked repository you will have to push your changes (more on that later). Before we do that, we should add a second remote repository, which is the main repository. This is normally called upstream (you should use the same naming convention so you can easily follow other instructions later)

$ cd pongball
$ git remote add upstream https://github.com/Double-Fine-Game-Club/pongball.git

Committing your changes

To save your changes to your current repository (remember, you are working on a local repository) it's not enough to just make the file changes, you must update the repository itself.

To see the pending changes just type

$ git status

Modifying files will automatically appear as modified in the status. However, to add a file it's not enough to add it to the directory. You need to add it to the repository as follows:

$ git add <filename>

Files that are not in the repository, but are in the directory are 'unstaged'. Take special care not to add unnecessary files. Some of the files are generated by Unity and should not be part of the repository.

To revert a change you have done to an existing file use the following command:

$  git checkout -- <filename>

This will give you a fresh copy of the unmodified file (note that you will lose your local changes)

To unstage a file you added use the following command

$  git reset HEAD <filename>

Finally, to save your changes you should use the commit command. It's very important to add a meaningful message on what you have done. This is good practice so others understand your commits. So for example:

$ git commit -m "Issue #33: Fixed ball catching fire when space is pressed"

We will not going into further details here on these basic commands, you can find a lot more right here

Branches

So you are ready to go, right? Well, not yet. There's a very important aspect for you to learn which is branches.

The main branch is called 'master'. This is where the latest code is always available. By default, when you cloned your repository you are set to work on this main branch. However, changing your code in master is bad practice. It is much better to start using branches. Even if the change seems small, it is still highly not recommended to do these on master. There are several reasons for that. The first is that branches allow you to create granular changes. It will be easier for others to understand what you've done. The second reason is that it will be much easier for you to work on other things while your changes have not been integrated yet. It may seem like an annoyance at first, but do trust us this is in fact easier to work this way, mainly because you are not developing here alone.

Recommended reading: here

Creating a new branch

Suppose you want to create a new ball model. Then let's create a branch for that

$ git checkout -b my_ball_model

Note that the '-b' switch creates the branch, and the checkout command switches to that branch. if you don't like using that switch and prefer using 2 commands then do the following:

$ git branch my_ball_model
$ git checkout my_ball_model

Using the above single command or two commands is equivalent so use whatever you find easier and less error-prone.

Multiple branches

You can have as many branches as you'd like. Suppose you are still in the middle of creating your ball and would like to add a new tree type. This has nothing to do with the ball, so we should branch off from the master again. First go back to the master branch

$ git checkout master

Now, simply create your second branch

$ git checkout -b great_tree

Merging branches to master

At some point you'll want to merge changes of your branch back to master. This is rather simple, just switch to master and merge:

$ git checkout master
$ git merge my_ball_model

Merging master to branches

You will most likely update your master branch from time to time to be up to date with the latest main repository changes (details next section). If you'd like your branch to also be up to date you can simply merge the master to your branch. The procedure is exactly the same, while you are in your branch do

$ git merge master

In fact, remember this part, it will be useful later.

Working with remotes

push

Remember that your changes are all local even after you commit your changes. To apply your changes to your forked remote repository simply can simply push your changes to the origin. To push the master branch back to origin do:

$ git push origin master

You cannot push directly to the 'upstream' remote we created. That requires a pull request which we'll explain in a moment.

Keeping Your Repository Up To Date

Obviously you are not alone. Other continue to work on the game while you make your own changes. The simplest way to be up to date is to use the pull command (reminder: upstream is this repository)

$ git pull upstream master

This will take the changes from master in upstream, and merge them to your own branch. Notice that the merge is done to your current local branch, so if you'd like to pull into master only and not your branch, ensure you checkout master first.

It's probably best you first pull changes from upstream to your own repository master before merging changes from a branch. This way you can address conflicts while doing the merge, and if they are difficult to solve you can go back and still have an up to date master branch.

Pull requests

Finally we arrive at the point where you can submit your code. You can make pull requests to ask the people maintaining the main repository to merge your changes. Of course you should do that when you're done. Github allows an easy interface to do that.

It's best practice to create pull requests for your branches. If you properly followed the recommendations here you should have a branch per specific topic. This will allow you to make multiple contributions without having to worry when the pull request has been approved (it's not uncommon for pull requests to be handled only after a few days). This means you can continue working uninterrupted on any other task.

Before making the pull request you should make sure you pulled the latest from upstream and merged those changes into your branch. This will ensure you have resolved all possible merge conflicts and it will mean much quicker and easier response to your pull request.

Open issues

Issues are created, or can be created, whenever a change is requested for the project. This includes all of implementing a feature, fixing a bug, creating a model, and writing documents for this Wiki. An issue consists of a subject for the issue and a description where full details can be provided about what the issue wants resolved as well as attachments. Issues also provide a place for contributors to discuss possible solutions for the requested changes. Each issue is automatically given an issue number by GitHub e.g. #24.

Mistakes and pitfalls

Adding unwanted files

Refrain from adding files that are auto-generated by Unity. Doing so would not only unnecessarily increase the repository size, but it will also make tracking changes an impossible task. If you added those inadvertently do not just delete the files and make another commit. Git will remember those actions which again will be difficult for everyone else later.

It's best you contact the community here if that happens, do not create a pull request with such changes.

TBD

Should we require squash merge to have a single commit before merge? (probably requires creating a branch just for merge, a bit more complex but cleaner)