A minimal git work flow

Preface

Target audience

This is intended to allow working together with other people using git. It will only cover the bare minimum of a very simple work flow ignoring many advanced, medium, and even basic features. The target audience are people who don't want to invest a lot of time in learning git but need to know the bare minimum to use it, because their collaborators forced them to do so. There's a summary/short version listing the discussed commands at the very bottom.

Disclaimer

If you really want to learn git, please ignore the present page and consult one of the many good git tutorials, for example the Pro Git book. More information is available on the official git documentation webpage.

Introduction

Git is a distributed version control system. The main idea is, that every user has its own copy of the repository including its wn history. In the following we assume in addition that there is one central version of the repository on a server. The history of different copies may be different and keeping them in sync (to some extend) requires to take explicit action. In this setting there are essentially three types of operations:

The following describes a very simple work flow ignoring e.g. the possibility to use several branches. In git terminology this means that we will only consider working on the so called master branch. The described work flow roughly resembles, the classical work flow implemented by Subversion. In all commands described below <arg> is a placeholder for an argument and [<arg>] is a placeholder for an optional argument.

More details (can be skip on first reading)

It should be noted that this is just one possible work flow and that git allows to do a lot more. For example you can work with multiple branches of a repository, sync with multiple servers, distribute commits by e-mail, modify the repository history afterwards. Also a central server often comes with a nice web front end that allows to nicely view the history, track issues, setup automated test environments, manage merge requests for development, review, and integration of features using multiple branches, etc.

Getting your copy of the repository

To get a copy you need to clone an existing repository which is often located on a server. A repository located under some given <adress> can be cloned using

git clone <adress> [<name>]

If an optional [<name>] is given, the latter is used for the generated directory. Otherwise the directory is named according to the repository. Often, a repository can be accessed using different protocols encoded in the adress (e.g. git@git.imp.fu-berlin.de:owner/repository.git or https://git.imp.fu-berlin.de/owner/repository.git). In this case the git@... variant is preferred if you later want to write to the repository. Notice that this requires properly setup credentials, which should be no problem, if you have done this before for the server.

The local clone/copy of the repository will not be synchronized automatically (like e.g. Dropbox or Nextcloud) but only once you explicitly initiate this using the command given below.

Working with your local repository

In contrast to Subversion you can work with your local repository independently of the repository on the server. In order to do this git manages files by using three different categories. The versions of files that have been commited and are part of the history are what makes up the repository which is stored in the hidden .git subdirectory. The normal files that you can see and access in the directory are denoted as working tree. Modifying or adding files in the directory only changes the working tree and leaves the local repository unchanged. Finally the index is a list of files to be marked for committing.

One or multiple modified files in the work tree can be committed using

git commit <file1> <file2> ... -m"[short describtion of your changes]"

This will store your modified versions to the repository by creating a new commit/revision. If you simply want to commit all locally modified files this can be achieved using

git commit -a -m"[short describtion of your changes]"

In both versions the index is not involved. Alternatively you can mark several files for committing using

git add <file1> <file2> ...
...
git add <file3> ...

This will add the given files to the index. Later you can commit all files in the index using a plain

git commit -m"[short describtion of your changes]"

While both versions work for modifying existing files, you need to use the second one for new files

git add <newfile>
git commit -m"[short describtion of your changes]"

The message should briefly describe what your change was about, e.g. "Add theorem on bla..." or "Make all text pink since I like this more". Omitting the message will open an editor for you to enter it. If you find your self in the seemingly nerdy VI-editor you may exit it using :q! and retry giving the message on the command line.

To see the status of your repository you can use

git status

This will list all locally modified files in the work tree, all files staged in the index, and all unknown files. Furthermore it will show some information on how your local repository differs from the latest known state of the central repository.

Syncing local and central repositories

All add and commit actions will only modify your local repository. In order to apply your changes to a central repository or get updates form the latter you need to synchronize your repository. To the end git automatically stores information on the location of the original repository when creating your local clone. (This is called a remote in git terminology.)

Updating the local repository

The easiest way to get updates from the central repository is

git pull -r

This will first download the latest version of the central repository, then bring your local repository to the state of the latter, and finally try to reapply your local commits on top of this. This way of combining two states (local and the central repository) is called rebasing. It's a good idea to do this before you start modifying files locally. If this succeeds, git status will normally tell you, that your local repository (to be precise its master branch) is ahead of the remote repository (origin/server).

Sending you changes to the central repository

Now you can push your changes to the server using

git push

Then the central repository will be on the same state as the local one. If the central repository was meanwhile modified (by someone else doing a git push), then pushing will fail because you first have to do git pull -r again. This way merging of different versions will always happen locally to avoid generating a broken version on the server.

More details (can be skip on first reading)

In fact you can do the above in a more fine-grained way. To only download the latest information from the server without modifying your local repository you can use

git fetch

Afterwards git status may (or may not) tell you that your local repository (master) lacks behind what is now known from the central one (origin/master). Similarly you can update your repository from the currently known information without downloading utilizing the rebasing strategy outlined above using

git rebase

Hence git pull -r is equivalent to git fetch; git rebase. There is also another strategy for combining two states of a repository. Using

git merge

will not try to apply one sequence of changes on top of the other but combine the final state of both. In contrast to git rebase this may lead to a diamond-like history. Again you can do a combined git fetch; git merge using git pull.

Short version

Clone existing repository:

git clone <adress> [<name>]

Update local repository:

git pull -r

Add new files (mark for committing):

git add <new file>

Commit files:

git commit <file1> <file2> ... -m"[short describtion of your changes]"

Sent you changes to the server:

git push