Git Tutorial
AlliedModders now hosts some of its repositories on Git, via GitLab: https://labs.alliedmods.net/
Contents
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 GitLab for repository hosting and code review. GitLab 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 "merge request" for the original developer to accept them back. For Git projects, we use this workflow instead of patches.
Installing
See this article for how to install and setup Git. If you intend to send Merge Requests, you should read the section about authentication. AlliedModders supports both SSH authentication (via git.alliedmods.net) and HTTPS authentication (via labs.alliedmods.net).
Getting Code
If you have either forked an AlliedModders project on GitLab, 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]/am/repository
Substitute your forum 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:
git clone https://labs.alliedmods.net/am/amxmodx
Workflow
Code reviews and patch submission should take place on GitLab. 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 GitLab.
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. GitLab can host personal copies of other repositories for you, called "forks". To fork a project, log in to labs, then visit the project's page. For example, AMX Mod X is at https://labs.alliedmods.net/am/amxmodx. 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://labs.alliedmods.net/am/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. 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
Merge Requests
Once your branch is ready for submission, the next step is to create a merge request. First, push your branch back to Labs:
git push origin eggapi
Then, visit your dashboard on GitLab. You should see a new entry under "Recent Activity", with a "Create Merge Request" button:
After clicking that button, you'll get a screen where you can pick the source and destination branches, write a description, and optionally assign someone to the merge. Here's what it might look like to merge my local "egg" branch into AMX Mod X master:
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. GitLab 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 GitLab 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 Merge Request model 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 branch, go ahead! The goal of using git 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 GitLab 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