Git for dummies

This is a very clear and simple cheat sheet that describes all you need in order to use the content tracker Git and Gerrit . It should give you at least the minimal knowledge needed in order to push to all major repositories we use, including these on GitHub and other sites.

If you are a git expert, you are welcome to improve this manual, but please keep it extremely simple.

Installing git

Windows

Download installer, which installs a terminal version that is similar to linux one

Git will install a complete M-SYS with terminal version, called git bash as well as GUI version. It's strongly recommended to use git bash for everything, this guide doesn't cover any GUI clients for git.

MacOS

There should be a package at https://git-scm.com/download/mac or you could just compile it yourself!

Linux

For some weird reason, the git package in Debian and Ubuntu is called "git-core" and git doesn't link to it. Getting git-core will install it.

On other distro's visit https://git-scm.com .

Setting it up

You need these in order to push:

Terminology

VCS

Abbreviation for the generic term "Version control system". "Git" is one of many VCS's.

Git

Content tracker created by Linus Torvalds. Git, unlike many other VCS's is distributed, which means that everyone has a copy of whole repository, instead accessing it through a central server.

Branch

Makes it possible for you to diverge from the main line of development and continue to do work without messing with that main line. Usually, you want to make all your changes in your own branch instead of writing them to master one.

Revision

When you commit your changes, a new revision is created. History in git, consist of revisions. Every revision has a commit message and unique ID.

Remote

Repository that is hosted on remote system, usually accessible through ssh or https.

Repository

Base for all content that is tracked by git.

Origin

In git default alias for remote repository you cloned is called "origin". If you clone repository foo from server "http://bar/foo.git" that will be your origin.

Master

Git's default branch that is usually created upon creation of repository, but doesn't need to be. It's most common name for a default branch of a repository, but it doesn't need to be. (Just as superuser in Linux doesn't need to be called root, but almost always is).

Gerrit

Review system built on top of Git. It allows experienced developers to review changes made by others and merge them into master branch.

Guide

Download the repository: clone

Initial checkout - called "clone". Fetches a remote repository from a remote server and save it to local folder.

git clone <repository goes here>

Example:

# Download a read-only (you can't push) copy of huggle using http
git clone https://github.com/huggle/huggle3-qt-lx
# Download a read-only copy of huggle using http to folder "foobar"
git clone https://github.com/huggle/huggle3-qt-lx foobar

Update the downloaded repository: pull

  • update your copy of repository with the version on remote server
git pull
  • update which automatically merge stuff - called rebase, update the repository and merge it with your commits
git pull --rebase
Edit conflicts

It often happens that you run into an edit conflict. That is annoying, but git has fairly good mechanism to deal with them. There is a magic command

git mergetool

You can also install some 3rd editor such as kdiff3 that will open a nice GUI which can help you with merging, mergetool will then ask you which editor you wish to use.

If you are using gerrit: This command does not work for downloading new versions of a gerrit patchset. For this use case, it's probably easiest to just run git review -d <number> where <number> is the gerrit change number to download the patchset to a new branch, and work on that instead. Note that if you have previously used git review -d to download a patchset and made changes to it, but have not uploaded the changes to gerrit, running the command again would destroy all local changes, so you should first use git checkout -b branch_name to copy the local changes to a new branch if you want to preserve them.

Check what has been changed: diff

In order to see what you changed before you commit do:

git diff

In order to see what you changed after commit do:

# compare current head with previous commit, that mean it compare what you just committed with what was there before you did that
git diff HEAD^1
# compare with any given id
git diff <commit-id>

Create your own branch

You can view all branches that were ever checked out on your local copy using

git branch

If you want to create a new branch, forking the branch you are currently on, use

git checkout -b <branch_name>

If you want to push your branch to origin

git push origin <branch_name>

Save the changes: commit

Unlike in svn, the committing is done locally and then it needs to be sent to server (using git push) or for a review (using git review).

You need to specify which files will be committed. Even if you change the file it won't be committed, unless you tell git to do that. You can use command git add in order to make it commit the changes

# insert a file to commit
git add file2
# in case you decided that you don't want to commit file2 you can revert the git add by doing git reset file2
# Or all pending changes with just: git reset  (but this won't change the files on disk)
git add file.cpp
# commit only the files which were marked with git add
git commit
# or commit also all files tracked by git which were changed
git commit -a
In case you want to abort the commit, most easy thing to do is remove the commit message from editor, save and quit. Git will not allow for a commit with empty commit message

In case you want to change the commit you just made, do

git commit --amend
# for example you forgot to add important_thing.c
git add important_thing.c
git commit --amend

that will change the content of existing commit, if you already pushed it, then this can't be pushed to remote again as you changed something what already exist, do this only if you didn't push yet

Now that you committed the change, you may be ready to push it.

Merge multiple commits: squash

Gerrit doesn't like too many commits in 1 push, so that you need to occasionally make 1 commit of multiple (that is called squashing).

# backup whole repository
cp -r . /tmp/backup
# request git to merge two last commits (HEAD and previous 1 commit)
git rebase -i HEAD~1
# leave pick near to message you want to keep, change all messages you want to merge to "squash" like
# sometimes it is needed to do this
git rebase
# now you can try to push again
git-review -R
# or
git push

Viewing the status of a branch: git status

git status

Viewing the commit log for a branch: log

git log

Press 'q' to back out of this view.

Upload your commits, branches or tags to server: push

When everything is fine

Ideally you type git push and everything works. Unfortunately, that works rarely.

When it's not fine

  • You get rejected because you don't have permissions:
    • You may have missing username in url, everytime you ssh somewhere, you need to specify your username (petrb@server.com)
    • You checked out using http
      • You can change the url in .git/config
    • You really don't have permissions
      • You need to contact the owner of repo
  • You are missing some hooks
    • Gerrit requires the commit-msg hook (this may no longer be required)
scp -p -P 29418 username@gerrit.wikimedia.org:hooks/commit-msg .git/hooks/
git commit --amend
  • There were some updates and you are not up to date
git pull --rebase
  • You are using wrong command to push
    • Sometimes it's needed to use following, should you know why, feel free to explain it:
git push origin HEAD:refs/publish/master
  • Some repositories have own system
git push-for-review-production
  • Some repositories require git review
git-review -R

If you are using git-review you need a .gitreview file in a repo, if it's not there, you need to create it:

[gerrit]
host=gerrit.wikimedia.org
port=29418
project=  here you add a relative path example: labs/toollabs.git
defaultbranch=master
defaultrebase=0

Resetting the repository: reset & stash

Git makes it very hard to revert the changes or reset the repository to original state as it was when you cloned it. In svn, you can simply delete the files and run svn up which restore them. In git doing so has no effect.

There are many ways to reset the repository to original state, but I found it simplest just to delete it and clone it again. In case it's a huge repository, you probably don't want to waste time and try these:

# soft reset - this will reset all git add <whatever here> - this will NOT reset any changes you have done to files
git reset
# revert all commited files to version they had after last commit - this will revert all changes to file you have done to latest commit
git stash
# hard reset
git reset --hard origin/master
# if you want to revert all changes to all files and remove all files that were added since last commit,
# restore all files that you removed, basically you want to revert repository to what it was since you cloned it
# or commited, get to root of repository (where .git is) and delete everything except .git
rm -r *
git stash

Gerrit specific

Installing git review

Ubuntu / Debian

sudo apt-get install git-review

Downloading a patchset from gerrit

git review -d 31337

This downloads the contents of https://gerrit.wikimedia.org/r/c/31337/, puts them in a new branch, and switches to the branch.

Rebasing a patchset on master

First, try clicking "Rebase" in gerrit. If that fails, make sure everything is committed, and then run

git checkout master
git pull
git checkout branch_name
git rebase master

Follow the on-screen instructions.

Examples

# configure git
git config --global user.email some.guy@example.org
git config --global user.name Petrb

#########################################
# GERRIT
#########################################

# get a repo
git clone https://gerrit.wikimedia.org/r/mediawiki/core.git mediawiki
cd mediawiki
# now, do some changes and commit them:
git commit -a
# now push them
git-review -R

#######################################
# GITHUB
#######################################

# get a repo
git clone git@github.com:huggle/huggle3-qt-lx hg
cd hg
# checkout new branch
git checkout -b feature
# now, do some changes and commit them:
git commit -a
# now push them
git push origin feature

See also