User:Petrb/Git for idiots

Because nearly every time I work with gerrit I feel like an idiot, I decided to make this simple guide for git and gerrit. In case you feel same stupid as I do, it may be useful for you, feel free to update this page, but try to keep it stupid people friendly :)

Please note: If you really need to use this guide to understand git, it doesn't imply you are an idiot, rather it implies that git is complicated.

Windows
I don't use windows that much, however you should try http://git-scm.com/download/win which installs a terminal version that is similar to linux one

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

Linux
For a weird reasons 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 git-scm.com

Setting it up
You need these in order to push:
 * account on wikimedia gerrit or any other git repository hosting
 * e-mail
 * name
 * public / private key - http://git-scm.com/book/en/Git-on-the-Server-Generating-Your-SSH-Public-Key
 * lot of patience
 * lot of beer (as you get more and more frustrated, drink it and git will look awesome to you again)

you can configure your username and e-mail by typing (please use your own mail and name): git config --global user.email name@blah.com git config --global user.name Name

Everytime you clone, use ssh and prefix the URL with username@, eg. ssh://petrb@wikimedia.org or you won't be able to push. If you forgot to do that, you can open .git/config and change the url there.

VCS
Version control system - GIT is one of many VCS's

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 for 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).

Download the repository: clone
Initial checkout (svn checkout) - called "clone". Fetches a repo from remote server and save it to local folder. git clone

Example: git clone http://github.com/huggle/huggle3-qt-lx git clone http://github.com/huggle/huggle3-qt-lx foobar
 * 1) Download a read-only copy of huggle using http
 * 1) Download a read-only copy of huggle using http to folder "foobar"

Update the downloaded repository: pull
git pull git pull --rebase
 * update (svn up) - called pull
 * update which automatically merge stuff - called rebase, update the repository and merge it with your commits


 * 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.

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:

git diff HEAD^1 git diff 
 * 1) compare current head with previous commit, that mean it compare what you just committed with what was there before you did that
 * 1) compare with any given 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 

If you want to push your branch to origin git push origin 

Save the changes: commit
Unlike in svn, the committing is done locally and then it needs to be sent to server (using git push), that has some advantages and tons of disadvantages (git initial clone takes way longer, the repository is huge and hard to manipulate)

Unlike in svn 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 git add file2 git add file.cpp git commit git commit -a
 * 1) insert a file to commit
 * 1) in case you decided that you don't want to commit file2 you can revert the git add by doing git reset file2
 * 2) Or all pending changes with just: git reset  (but this won't change the files on disk)
 * 1) commit only the files which were marked with git add
 * 1) or commit also all files tracked by git which were changed

In case you want to change the commit you just made, do git commit --amend 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
 * 1) for example you forgot to add important_thing.c

Now that you committed the change, you may be ready to push it. But that's where the pain begins :)

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). This is IMHO a step back because using this feature effectively kill the change history and purpose of versioning software at all. But this is just my opinion and it is not in my powers to convince gerrit maintainers to disable this requirement... So here is a guide

Upload your commits, branches or tags to server: push
This is a biggest evil of git for us, idiots :)

When everything is fine
Ideally you type  and everything works. Unfortunately, that works rarely.

When it's not fine
scp -p -P 29418 username@gerrit.wikimedia.org:hooks/commit-msg .git/hooks/ git commit --amend git pull --rebase git push origin HEAD:refs/publish/master git push-for-review-production git-review -R
 * 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
 * There were some updates and you are not up to date
 * You are using wrong command to push
 * Sometimes it's needed to use following, should you know why, feel free to explain it:
 * Some repositories have own system
 * Some repositories require git review

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:

Examples
svn checkout - clone