Git Tutorial

From AlliedModders Wiki
Jump to: navigation, search

AlliedModders now hosts some of its repositories on Git, via GitHub. There are two ways you can browse these repositories:

Getting Started

Introduction

Git, like other version control systems, has a few concepts important to working with source code:

  • Repositories are where source code is stored.
  • You download a repository via cloning.
  • You update a repository by pulling or fetching.
  • You add changes by committing.
  • You upload changes to a remote repository by pushing.
  • You resolve repository differences by merging.

AlliedModders uses GitHub for repository hosting and code review. GitHub allows you to "fork" a repository, which gives you your own hosted copy where you have write access. After forking a project, you can make changes, then submit a "pull request" for the original developer to accept them back. For Git projects, we use this workflow instead of patches.

Installing

See this article on GitHub for how to install and setup Git. If you intend to send Pull Requests over GitHub, you should set your username and password as described.

Getting Code

If you have either forked an AlliedModders project on GitHub, or you are a developer with write-access to one of our repositories, you should clone a repository like so:

git clone https://[email protected]/alliedmodders/repository

If you have SSH keys set in your GitHub profile, which we recommend, you can use Git via SSH:

git clone [email protected]:USER/repository

Substitute your GitHub username for USER, and if you're cloning a fork, the path to your fork rather than the upstream repository.

If you just want read-only access, you can use one of the following URL forms:

Note that git.alliedmods.net is a read-only mirror of our GitHub repositories.

Workflow

Code reviews and patch submission should take place on GitHub. Bug reporting and issue tracking, if needed, should still occur on Bugzilla. Most of the time, you will not need to use Bugzilla. If you just want code reviewed and checked in, you can use GitHub.

With Git, all work is usually done in branches. A branch is a separate line of development that exists alongside main development. Branches have their own commit history, and can be merged back to the main line of development (called master). Branches can be deleted or shared. The crux of the Git workflow is as follows:

  • Create a new branch.
  • Commit changes onto the new branch.
  • Ask the upstream repository to merge the branch.
  • Delete the local branch, switch back to master, and sync up.

This is significantly less work than the Mercurial patch-sharing model, where patch files have to be exported into a bug tracker.

Now for the details. There are two workflows, one for AlliedModders developers and one for contributors. The processes are basically the same, but official developers can skip a few steps. If you are a developer, you can also choose to use the contributor workflow.

Contributing via Forks

This is the default workflow. GitHub can host personal copies of other repositories for you, called "forks". To fork a project, log in to GitHub, then visit the project's page. For example, AMX Mod X is at [1]. Just click the "Fork" button in the upper left, and you will have your own copy of the repository.

Setup

Once you have a fork, you can clone it and add the upstream repository as a remote source:

git clone https://[email protected]/USER/amxmodx
git remote add upstream https://github.com/alliedmodders/amxmodx

Branching

Whenever you are about to work on something, it's a good idea to sync your local repository to make sure it's up to date. For a more in-depth look at this, see syncing a fork at GitHub. In short, you just need to do:

git checkout master       # Switch to main branch
git merge upstream/master # Merge changes from upstream

Now, let's say you want to work a new feature or bug called "EggAPI". First, create a branch for your work:

git checkout -b eggapi

This creates and switches to a new eggapi branch, forked from the position of the previous branch. Use git checkout to switch branches, and -b to create new ones.

Committing

After you've made changes, use git commit to commit them. Note that unlike Mercurial, git does not recognize changes unless you stage them. For example, let's say I modify amxmodx/string.cpp. If I try to commit, or run git status, I might see something like:

# On branch eggapi
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   amxmodx/string.cpp

This is because my changes are not yet staged as part of the next commit. To stage them, and then commit, I can do:

git add amxmodx/string.cpp
git commit

Pull Requests

Once your branch is ready for submission, the next step is to create a pull request. First, push your branch back to GitHub:

git push origin eggapi

Then, visit your repository on GitHub. You should see something like:

Pullrequest.PNG

Click "Compare & pull request". This will send an e-mail to the development team, and a developer can then review your changes and merge them into the master branch. GitHub will then provide a button to delete your branch, and you can also remove it locally with:

git checkout master
git branch -D eggapi

Congratulations! You're done. If a developer requests changes, you can commit, and push to your branch again. Note that GitHub won't tell the developer that you've updated your branch. It's a good idea posting a comment saying that your request is ready for re-review.

Developers

If you're an AlliedModders developer and have write-access to the official upstream repositories, your workflow is basically the same as contributors'. However, you have extra options available:

  • You can skip forking, and instead push your branches directly to the upstream repository. You can then create a pull request off the main project page, just as you would for a fork.
  • You can push directly to the master branch of the upstream repository. This means you can continue to use the Bugzilla workflow of exporting patches, reviewing them in the bug tracker, and then pushing them after review is complete.
  • You can merge pull requests yourself, rather than waiting on a developer.
  • If you clone upstream, instead of merging upstream/master, you can pull origin/master.

Code Review

Git does not change the AlliedModders policy of requiring peer review for all code changes. Unless you are fixing a broken build, all patches should be reviewed by another AlliedModders developer. Previously, this meant exporting a patch file to Bugzilla. You can still do that, but it's a very burdensome process for both developers and contributors. For Git projects we recommend the Pull Request model via GitHub, explained earlier.

  • If you are submitting a pull request (PR), and you want a specific developer to review your changes: you can assign them to the PR, or just e-mail/message them the link. If they request changes, and you push new commits to the branch, the PR will update automatically. However, it will not send notifications. It's a good idea to post a comment saying that the changes are ready for re-review.
  • If you are reviewing another developer's PR, in general it's best to let them be responsible for merging it. All you have to do is review the code, and once it looks good, say something in the comments like "r=me", ":ship:", ":+1:", whatever tickles your fancy.
  • If you are reviewing a contributor's PR, then they won't have access to perform the merge themselves. In this case, once the code has been reviewed, you can just merge it for them.

YOU HAVE THE POWER!!!! If you think you're qualified to review and merge a contributor's PR, go ahead! The goal of using GitHub is to make the contribution process much more accessible, and fast response from developers is the best way, BY FAR, to keeping contributors.

Mercurial Commands

If you're coming from Mercurial, here are some Git command equivalents. The basics are the same:

  • clone
  • commit
  • push
  • diff (note: only shows unstaged diff)
  • status
  • add
  • log

Others:

hg pull
git fetch

hg pull -u
git pull

hg strip tip
git reset --hard HEAD~1

hg revert file
git checkout -- file

hg revert -a
git checkout -- .

Instead of mq, you can use branches, which are usually much more convenient anyway, since you can just commit changes as you go and easily switch between them. Exactly replacing mq is out of this article's scope, but the tools exist.

hg qnew xxx
git checkout -b xxx

hg qpu xxx # if stack is empty
git checkout xxx

hg qpop  # for 1-deep stack...
git checkout master

hg qref
git add x y z && git commit # or git stash

hg qfin -a tip
# No equivalent, though you should switch back to master after a PR is done.
# You can also delete branches via: git branch -D xxx

hg qdiff
git diff xxx..master   # e.g. git my-branch..master

SSH Authentication

If you have SSH Keys, you can set your GitHub profile to accept them. This is HIGHLY RECOMMENDED for AlliedModders developers. You probably already have a key with us, even.

Tips and Tricks

Set up a good merge tool. We really like Beyond Compare, however, kdiff3 and meld are also good.

If you accidentally commit to master, you can copy the commit to a new branch, then erase the commit off master:

git branch stuff
git reset --hard HEAD~1

You can list branches with:

git branch