The `531019e7119268c4dae5ac44ef5929165794f4b0` points to the tree object which points to the two committed files.

In git, there are 3 areas:
- The **working area** (everything in `alpha/` except the folder `.git`)
- The **staging area** (in the `.git` folder)
- The **repository** (also in the `.git` folder)

The repository is a chain of commit, beginning with your first commit.
### Navigating a git repository
Let’s create a new commit with the changes made to `data/number.txt`:
```sh
echo"2"> data/number.txt
git add data/number.txt
git commit -m"a2"
git st
git lo
```
You have a second point in your commit history.
You can navigate to a given point of the repository with the command `git checkout`:
```sh
git log
cat data/number.txt
git checkout 531019e
cat data/number.txt
```
> You don't have to give the complete commit identifier for the command `git checkout`, only an unique subset of it.
The state, of the file `data/number.txt` is back to the one at the time of the first commit.
The `git checkout` or `git co` command rewrite your whole working area to match the state of the targeted commit.
```sh
git log
```
The `git log` command doesn’t display your second commit anymore.
Git commits only know of their direct ancestor(s).
The other change is in the first line of the `git log` command:
`(HEAD -> master)` became (HEAD).
This change means that you are in a **detached HEAD** state , the command `git st` also gives you this information.
```sh
git st
```
In git commit are chained one after another starting with the first commit.
Therefore, you can always go back to the commit history.
The repository is not only made of commits, but also of labels.
Labels point to a commit and can be the target of the `git co` command.
They are two types of labels:
- branches
- tags
If the first commit is the root of a growing tree of commits, branches are labels pointing to the leaves of the tree.
They change after each commit from pointing to the ancestor of the new commit, to pointing to the new commit.
The default branch in git is called `master`
Contrary to branches tags are anchored to a fixed commit.
**HEAD** is a special label that indicates your position in the tree of commits.
You can add a tag to your first commit with the command `git tag`
```sh
git tag -a v0.1 -m"my version 0.1"
git tag
git lo
```
You now have one tag in your repository.
The commit `c7a4cb9` is pointed by the tag `v0.1`.
```sh
git co master
git st
git lo
```
We are back at the leaf of the git repository.
## Growing the repository tree
We only have one branch, the `master` branch in our repository.
This means that we only have one timeline in our history.
In git, you can have as many branches as you want, to test out things, for example.
The following command creates the branch `dev` and move us (**HEAD**) to it.
```sh
git co -b dev
git st
git lo
```
```sh
echo ’3’ > data/number.txt
git add data/number.txt
git commit -m"a3"
git lo
```
If we have two branches `dev` and `master`, it’s hard to tell them apart (`master` is shorter).
```sh
git co master
echo'b'> data/letter.txt
git add data/letter.txt
git commit -m"b2"
git lo
```
Congratulations, you have a fork in your git repository !
Let’s make another one called `dev2` from the branch `master` where `data/letter.txt` contain the letter `c`.
Then create the corresponding commit `c2`
## Merging branches
When you are ready to incorporate your new code in your main branch you need to merge the branch containing the new code into your main branch.
You can merge branches with the command `git merge`.
This command is going to try to merge the targeted branch into the branch you are on (**HEAD**).
The command `git branch` shows you the available branches and the one you are on.
```sh
git branch
git merge master
```
Can we merge `master` into `dev2` ?
```sh
git co master
git branch
git merge dev2
```
There are three types of merge :
- Fast-forward
- Merge of two different lineages
- Merge of two different lineages with conflict
Here the branch `dev2` is a direct descendant of `master`.
`dev2` contain all the information contained in `master`.
For `master` to gain all the information contained in `dev2`, we just have to move the label `master` to the commit pointed by `dev2`
```sh
git lo
```
There is a fork between the branch `master` and `dev`, we have to merge two different lineages.
```sh
git branch
git merge dev
```
Here the command create a **merge commit**, a merge commit is a commit that has two direct ancestors.
A new commit means a new commit message to write.
```sh
git lo
```
The new commit is a `Merge` commit with the identifiers of its two ancestors.
Here, we didn't have any conflict: in the `dev` branch, we worked on the `data/number.txt` file while in the `master` branch, we worked on the `data/letter.txt` file.
Let’s complicate things !
Create a new commit `e3` in the `master` branch where the content of `data/letter.txt` is set to `e`.
Then create a new commit in the `dev` branch where the content of `data/letter.txt` is set to `f` and go back the branch `master`.
```sh
git lt
git branch
git merge dev
git st
```
The automatic merge failed due to a conflict in `data/letter.txt`.
You are now in a merging state.
You must solve the conflict by editing `data/letter.txt`.
You can see three things in the `data/letter.txt`:
- The state of the file in your current branch (**HEAD**)
- The state of the file in the last common ancestor of the two branches
- The state of the file in the merged branch (*dev*)
Edit `data/letter.txt`, to set its content to `f`.
Then complete the merge:
```sh
git add data/letter.txt
git st
git commit
git st
git lt
```
You, now, know how to deal with the different kind of merge
`file_handle.py` is a small python script to handle the dating and the access to dated files in a format compatible with the [guide of good practices at the LBMC](http://www.ens-lyon.fr/LBMC/intranet/fichiers/bioinfo/good-practices.pdf).
The `git clone <url>` command retrieves the whole history of a project and setup a working area based on the last point in this history.
> Note: repositories created on gitlab are _bare_ repository. There is no working
> or stash area on gitlab because nobody works on it.
At the end of the page [http://gitlab.biologie.ens-lyon.fr/<user_name>/git_basis](http://gitlab.biologie.ens-lyon.fr/<user_name>/git_basis) you have the following instruction to populate your remote repository
from an existing repository.
We can check the current remote addresses of our local git repository:
```sh
git remote -v
```
**origin** is set to `https://gitlab.biologie.ens-lyon.fr/LBMC/file_handle.git` for `fetch` and `push`
operation.
We want to add our repository to the remote addresses of our local git repository.
We are going to use `gitlab_lbmc` instead of `git@gitlab.biologie.ens-lyon.fr`
to match the ssh configuration file and use our ssh key in the connections to
Then we use the following commands to push our local copy to our remote repository:
```sh
git push -u perso --all
git push -u perso --tags# tags need to be pushed separatly
```
## merging branches
We want to merge our work with the **master** branch. What will the following
command do?
```sh
git merge master
```
Nothing. **master** points to an ancestor commit of the **tp1** branch.
However, the reverse operation is possible:
```sh
git checkout master
git branch -v
git merge tp1
git push perso
```
You can see the graph of our modifications at the following address [http://gitlab.biologie.ens-lyon.fr/<user_name>/git_basis/network/master](http://gitlab.biologie.ens-lyon.fr/<user_name>/git_basis/network/master)
When **W** tries to push his modifications to the remote repository he has an error because **C** made changes to it.
**W** has to get these modifications.
Git advises you to use the command `git pull`. We are not going to use this command and instead to:
```sh
git fetch
git status
git merge FETCH_HEAD
```
Those two commands do the same jobs as the command `git pull`, with the exception that we get to check what are the changes before blindly merge them.
There seems to be a conflict.
The command `git status` gives us the steps to solve this conflict.
In the working ares, the `README.md` file contains the information of this conflict.
````diff
<<<<<<< HEAD
To know how to use the `file_handle.py` script, enter the following command:
```sh
file_handle.py --help
```
=======
To use the `file_handle.py` script, enter the following command: ```sh
file_handle.py -f <INPUT_FILE>
```
if `<INPUT_FILE>` exists and is not dated `file_handle.py` will date it. Then `file_handle.py` will return the absolute path to the last version of `<INPUT_FILE>`.
>>>>>>> c470f055f499bc13fa64d90f3b5cb38314b34b6e
````
The section **HEAD** corresponds to the version of the **Usage** section in your local repository at the position of the **READ** reference.
The second section corresponds to the version of the **Usage** section in the remote repository for the commit **c470f055f499bc13fa64d90f3b5cb38314b34b6e**, the last commit of **C**.
To resolve it you need to edit it and then run the following commands to complete the merge:
```sh
git add README.md
git commit
git push
```
# Conclusion
You have performed a lot of basic and reasonably advanced git operations in a scenario with a central git repository.
To go further, you can study a few things that we did not cover here: