.. _git_introduction:
Git Introduction
================
This section will give you a brief introduction to `Git `_ and
`Gitlab `_ and how we use them.
.. contents:: Table of contents
:local:
:backlinks: none
Git and Gitlab
--------------
**Git** is a version control system for tracking changes in the source code of software
projects during development. **Gitlab** is a web application for version control based
on git. Among other things, it provides a wiki, an issue tracking system, and a CI/CD
pipeline system. CI/CD stands for continuous integration and continuous deployment and
roughly means that new code runs through a "pipeline" of automated tests before it is
integrated into the project. This way, errors and inconsistencies can be detected
quickly.
**Installation**
To install git, follow the instructions of the git book
in the chapter "`Installing Git
`_".
**Introduction**
If you have never worked with git before, check out this webpage of the entire `Pro Git
Book `_ for an introduction. Especially take a look at
the pages "`What is Git?
`_", "`Branches in a
Nutshell `_", and
"`Basic Branching and Merging
`_", to make
yourself familiar with the basic concepts.
**Git Repository**
A repository is a directory which stores all the files and data as well as metadata of a
project. A git repository is a repository that is controlled by git. A git repository
includes a complete version history of every file. The idea of git is that every project
member has a copy of the entire repository on their **local** computer. In order to
contribute to a software project that uses git for version control, you need to **clone
the repository**. That means, it is copied to your local computer from the **remote**
server, where it is stored.
The git repository of our project is called "pyddg". The cloning of pyddg happens when
installing pyddg according to the installation guide (see the `online docs
`_), when using the "git clone"
command.
Branching
---------
After having checked out the website "`Branches in a Nutshell
`_", you now know
what branches are. To summarize it again: A big software project with many people
working on it can easily become chaotic. The idea is that you don't want to mess up the
main line of development by all the small or specific changes. Instead, you want to
contribute your work to the main line of development when you have completed a task.
This is what branching is for.
In our case, **develop** is the name of the branch on which the latest stable version of
pyddg should always be found.
**Issue Tracking**
The work on the library is managed by issue tracking. **Every task/bug/problem is
formulated as an issue** in gitlab which is assigned to somebody. When there does not
exist an issue for a task, it probably should be created. Every project member has the
permission to do so.
**Related Branch**
Every issue (concerning the repository) has a **related branch**. All the changes in the
repository corresponding to an issue will take place on its branch. When you are
assigned to an issue that does not have a related branch yet, **create one** by clicking
on the little arrow next to "create merge request" and selecting "create branch". The
default **source branch** for every new branch is develop. That means the new branch is
a copy of develop in its current state. You can also use other branches as a source.
Committing
----------
When using the **git commit** command, a snapshot of the repository in its current state
on your branch is taken and stored. That makes it possible to recover this version of
the repository afterwards.
Commits should be based on **logical units**, as for example completed subtasks. It is
important to commit your work early and often to get a clear version history of your
code.
When committing, you must specify which of your changed files are affected.
**git add**
If you want to add a file to the commit, use git add to add a file to the so called
**staging area**. That means the files are gathered and wait to be committed together.
.. code-block:: bash
git add
**git checkout**
If you want to discard the changes in a file, use **git checkout**. These files will be
restored according to their previous version.
.. code-block:: bash
git checkout
After specifying which changed files in your repository are taken into account, you can
commit your work with the **git commit** command (see below).
**Commit Messages**
Each commit requires a commit message, which summarizes the changes that happened in
this commit. You can add the commit message to the commit command by using the option
'-m' with the message as a string.
.. code-block:: bash
git commit -m 'commit message'
**Vim**
If no commit message is specified in the commit command, the editor **vim** will launch
and ask you to write one. If you don't know how to use vim, you may panic because you
won't be able to write anything or get out. Luckily, you just need to know few commands
to add your commit message and leave.
1. Switch to insert mode by typing **i**
2. Now you can write your commit message
3. Get out with first pressing **escape**, then typing **:wq!** for 'write & quit!' and
**enter**.
Your commit is completed!
**Commit Message Conventions**
For a better overview, all commit messages should follow our conventions. See the docs
:ref: `commit-conventions`.
Switching to another Branch
~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is best, to switch to another branch when your working area is clean and you
committed or checked out all changed files. Then you can easily use the git checkout
command to switch to a branch:
.. code-block:: bash
git checkout name-of-branch
If you don't want to clean up the mess before you check out, check out this `page of the
git book
`_.
Transferring Data between Local & Remote Repository
---------------------------------------------------
You have already learned that the git repository is stored on each developer's local
server as well as on a remote server. As a consequence, it will happen that one version
of the branch is ahead of the other. The **git pull** and **git push** commands are for
transferring data between these two versions and updating the one who is behind. To find
out about the status of your local branch with respect to its remote version, you need
the **git fetch** and **git status** commands.
**git fetch**
That's the first thing you do when you want to check repository. This command downloads
the data of the remote repository - without changing your local one. That means your
local repository now knows the current state of the remote one.
.. code-block:: bash
git fetch
**git status**
The second thing you do is use the git status command. It tells you which branch you are
on, as well as whether your branch is ahead of, behind of, or up to date with its remote
version.
.. code-block:: bash
git status
**git push**
When working on a branch and committing every now and then, your local branch will be
ahead of its remote version. The git push command transfers the commits of your local
branch to the remote server.
When pushing, the code runs through the pipeline mentioned earlier. In the pipeline the
changes in code are checked through automatic tests before the remote version of the
branch is updated. If the tests fail, the developers will be notified. If the tests
pass, the changes will be accepted.
It is important to push to the server often, so your code is stored in a safe place.
Also, the latest version of your branch is made accessible to other developers. They
could be interested in the latest version of your work, since they may want to use part
of it.
Note, that you can't push to develop. This is our protected stable branch we use for
deployment of pyddg. Only maintainers can operate on that branch.
.. code-block:: bash
git push
**git pull**
There is always a lot going on on the branches of pyddg's repository. Busy developers
will push their work frequently and supply new features. That's why you should
regularly use fetch and status to check whether you are behind. If you are, you can use
the git pull command. It downloads the remote version of your current branch and updates
your local branch with the changes of the new version.
.. code-block:: bash
git pull
Merging Branches
----------------
If you are working on branch1 and want to use new features of branch2, you need to merge
branch2 into branch1. This can happen, if for example, you took a long time working on
an issue and the usage of functionalities you are using has changed. In this case, you
may need to merge develop into your branch. You can do so, by switching to the branch
you are working on and merging the other branch:
.. code-block:: bash
git checkout branch1
git merge branch2
Take a look at the page of the git book about `basic branching and merging
`_. Here, it
is explained very well!
Note, that you can merge develop into your branch but you can't merge into develop,
since only maintainers have the permission to do so. When you have finished your work,
you have to create a **merge request** (as explained in :ref:`workflow`).
**Merge Conflicts**
If the same part of the same file in two branches is changed differently, git can not
decide which of the parts is the right one to keep. In that case, the merge can't
happen automatically and has to be done manually. Use **git status** to check, which
files are unmerged. In these files, you will now find both versions of the code. The
version of your current branch is marked as "HEAD". For each conflicting part, **choose
one version or combine both**. When all conflicts are resolved, use **git commit** to
complete the merge.
Useful Git Commands
-------------------
A collection of some useful git commands.
Reverting changes
~~~~~~~~~~~~~~~~~
- revert all **uncommitted changes** on current branch
.. code-block:: bash
git reset --hard HEAD
- set branch to exactly **match the remote develop branch**
.. code-block:: bash
git fetch origin
git reset --hard origin/develop
- revert **last merge commit** on develop
.. code-block:: bash
git revert develop -m
The ```` is the index of the hash behind ``Merge: ...`` in the log
obtained by
.. code-block:: bash
git log -n 1
Git Overview
------------
Further, the following webpages can be helpful:
- https://git-scm.com/book/en/v2
- https://www.atlassian.com/git/tutorials/learn-git-with-bitbucket-cloud