Skip to content

Getting started with Git CLI and Github

riperiperi edited this page Jun 12, 2020 · 1 revision

A lot of contibutors to this project so far haven't had much experience with the open source process, so I thought I should write this guide to help direct you on a way to use git. It can be hard to maintain a fork and keep it all up to date without knowing the ins and outs of git, so this document will be a bit of a cheat sheet for those parts I know people have trouble with.

Can I use a helper tool like GitHub Desktop?

Yes. I don't really use these things myself though, so I am not sure about their featureset regarding working with upstream and remotes. It may be a good idea to read this page anyways to get an idea of what all of the terminology means.

Creating a Fork

The simplest part of developing for FreeSO is creating a "fork". A Fork is an online copy of the repository that you have full control over, that mirrors the source repository at the time of creation.

You need a fork to be able to submit your changes to GitHub, as by default only members of the organisation have write access to the repository. This is so that the entire codebase can't be replaced by pictures of Hannah Montana, or a money cheat directed at a single player.

When committing changes, you'll want to push them to your fork.

Cloning your fork

The easiest way to work with Git is to install it on your local machine, and clone your forked repository. You don't want to download as zip (even if making small experimental changes), as you will find it very hard to push any changes upstream if you want to.

Once your fork is created, use the green "Clone or Download" on its main page to get its git url, then clone it into a folder using the Git CLI:

git clone <git url>

This will make a "local clone" of your forked repository. This repository is separate from the version you see on github, which is the "remote" repository. To synchronize changes between your local and remote, use the following commands:

  • git pull: Pulls any new commits seen on the remote.
  • git push: Pushes any local commits to the remote.
  • git fetch <remote>: Lets you fetch from the remote.

Remotes

When you cloned your repository, the repo you cloned from was automatically added as the origin repository. However, you can add multiple remote repositories, which will let you work with branches in other repositories that you might not have read access to, if you want to merge, rebase or even switch to a branch to test it out. This is very useful for testing PRs, or keeping up to date with the main FreeSO repository.

The most obvious thing you want to do is add an upstream remote pointing to the main FreeSO repository. You can do so by using the following command:

git remote add upstream https://github.com/riperiperi/FreeSO.git

This lets you interact directly with the main repository for FreeSO, in a read only fashion, to let you create branches off of it and write them back to your own fork. Isn't git beautiful?

Now, you can fetch all changes to the upstream by using the following command:

git fetch upstream

This will fetch all of the upstream branches. Now,

Further reading: https://www.atlassian.com/git/tutorials/git-forks-and-upstreams

Creating a branch

When you fork your repository, you will automatically be in the default branch, master in the case of FreeSO. To keep things clean, you will want to keep each change you make to its own branch, so that you can send multiple Pull Requests at a time for different changes.

Since we added an upstream branch, we can easily create a new branch off of the top of the latest FreeSO develop at any time. develop is the branch we will be doing all "unsafe" development off of - master is managed by the organization members and drives the public release process, so we cannot accept direct merges to it.

Creating a feature branch (do this every time)

To switch your active branch to the upstream develop (read-only), use the following command

git checkout upstream/develop

You can't do anything in this branch, so you'll want to create a new one. The recommended naming format is feature/<name> or hotfix/<name> to keep things consistent in your repository (sort of git flow style), but there's no hard requirement for this.

To create a new branch:

git checkout -b <branch name>

This will create your new branch locally and switch you to it. To switch between branches, just do the same without -b:

git checkout <branch name>

Feel free to make any changes on this remote. When you attempt to git push for the first time in a branch, you will encounter an error message that tells you to set up the remote copy of the branch. Just go ahead and do what it says (if your fork is not origin, you will need to change that to what your fork's remote is actually called.)

Note: remote branches will be prefixed by the remote name, such as upstream/feature/test. local branches will not have a prefix, like feature/test. When you want to switch to a unique branch that exists on a remote (and there is not a name conflict) you should attempt to switch without the prefix, which will create a local version of that branch with correctly configured remote.

You want to do this same step of branching from upstream/develop every time, as it will make sure you're working off of the latest version of the FreeSO codebase.

Making changes

The git process is pretty simple. Make your local changes, git add them to a staged commit, and git commit them to the repository. You can then git push any of your local commits to the attached remote branch (on github, essentially making them public).

At any time, you can use git status to see which files have been changed. This will provide a pretty list of file paths relative to your current location.

To add any of them to a commit, use the command git add <relative path>. If you want to add everything from a specific folder, use the . character. For instance, git add . will add ALL changed files within the current directory and any subdirectories, and git add FreeSO/. will add ALL changed files starting at a directory called FreeSO.

You can see all files staged for commit with git status. When you're comfortable with your staged commit, make anime real by using the following command:

git commit -m "your commit message"

Your commit message should contain a short summary of what you have changed. If you want to open a text editor to make your commit message, just omit the -m parameter and message entirely.

To push to your remote, just do git push. Or not - you can stack multiple commits locally before pushing to the remote, if you're not comfortable with the changes going public yet. It's up to you!

Pull request

Pull requests are the backbone of the modern open source process. They are how you get your changes into the main repository, and allow the organizers to validate, review and ask for changes to your code beforehand. It's an important process to ensure that the quality of code in the repository stays high, and that nothing breaks the game.

When you push your changes to your fork, you can create a Pull Request in the main repository. Head on over to it, and you'll see a button at the top left "New pull request". Point it at your fork's branch, Make sure that you set the destination as develop, as we will not accept pull requests directed at the master branch.

Write a nice verbose description about what your changes do, and how they work. The pull request description is a full markdown field, and supports image uploads, so feel free to visually show changes. If needed, also list off any future work you intend to do, any potential issues with the implementation, or anything you specifically want comment on.

If you want to get comments on changes but want to make clear that it's not complete yet, create the PR with [RFC] (request for comment) in the title and set it as a Draft PR before submitting. Don't worry, it can be switched to a full PR later on.

Rebasing and Merge Conflicts

Oh no! Your pull request is stating that files cannot be merged, or one of the contributors is demanding that you "rebase" your branch, whatever that means. What nerve!

This is a common issue with Git - it's not magic, so if multiple people make changes to the same file it is likely that git will introduce problems when merging the changes together, or it may fail to merge them at all! This means that merging your branch will either break the game or just not be possible at all. What can you do?

The cleanest solution is to git rebase <branch>. This command will let you replay your commits on top of the target branch, allowing you to resolve these conflicts as they come up yourself.

It is likely that when doing this, the console will print that there was a CONFLICT in one or more files. This stops the rebase process, and requires you to resolve the conflict yourself.

You'll see that in the affected files, Git has added annotations showing what regions of the file could not be merged, and the two separate versions of that file.

<<<<<<< HEAD change 1 stuff

change 2 stuff

branch_name

Your job is to identify these regions and combine the changes in a way that makes sense to you. You want to make sure that your change is still reflected on top of what the develop branch now contains. Don't just blindly pick one of the branches, as it is likely that will undo someone else's change. You must respect both!

When you have resolved all conflicts, make sure that the game still builds and runs correctly. Make sure to specifically test the change that you made, to ensure the merge did not break anything around it. You then must continue the rebase using the following command:

git rebase --continue

More merge conflicts may occur in future commits. Resolve and continue as needed, and eventually you will be done (test your changes again after this!). You will now be out of sync with your upstream, so you will need to force push to your fork:

git push --force

Some text editors will help you find and manage merge conflicts like those shown above. Which ones? That is for you, to find out.

Stashing changes

Sometimes, you just gotta stash your changes to do something else, or switch to another branch. Just git add them all then type git stash. This will make your changes disappear so you can do whatever, then you can git stash --pop to get them back. You can stash multiple layers of changes, try to have fun with it.

Resetting changes

Sometimes, you just gotta start over. Use the command git reset to achieve this. To reset a branch to the state of another branch, use git reset --hard <branch name>. You may find git reset --hard upstream/develop useful to reset to the main FreeSO repo's develop branch.

Why are you so bad at writing!

Sorry, this is just my personal experience. If you want more information, the Atlassian Git Tutorials can provide more verbose descriptions, examples and help with more commands than this text wall.

https://www.atlassian.com/git/tutorials/