diff --git a/README.md b/README.md index fb526a221a6dbdf79352b7a5e636100eb8c493af..98b70e5a86b14455c98599c5936f56a239695dea 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ make The practical guide is decomposed in three sections. -- In the first part [ **Git Alone** ](./tp.md#part-1-git-alone), you will learn to use the basic Git command. -- In the second part [ **Git remote** ](./tp.md#part-2-git-remote), you will learn to interact with a Git remote repository -- In the last part [ **Git together** ](./tp.md#part-3-git-together), you will learn to work in collaboration with another person using Git. +- In the first part [ **Git Alone** ](./tp_1.md#part-1-git-alone), you will learn to use the basic Git command. +- In the second part [ **Git remote** ](./tp_2.md#part-2-git-remote), you will learn to interact with a Git remote repository +- In the last part [ **Git together** ](./tp_3.md#part-3-git-together), you will learn to work in collaboration with another person using Git. ## [Presentation support](./presentation.md) diff --git a/tp.md b/tp.md index f03811cc949040da03323fab9def3142d47ff8b2..80573c78142fac774e7ee08083f27c6e386fdd3f 100644 --- a/tp.md +++ b/tp.md @@ -109,7 +109,7 @@ Host gitlab_lbmc This configuration provides you with the shortcut `gitlab_lbmc` to connect to the `gitlab.biologie.ens-lyon.fr` server on the port `2222` under the `git` user, without using a password and using the identity key ` ~/.ssh/id_rsa_gitlab_lbmc`. -Finally, go to [http://gitlab.biologie.ens-lyon.fr/profile/keys](http://gitlab.biologie.ens-lyon.fr/profile/keys) and paste the content of the file ``~/.ssh/id_rsa_gitlab_lbmc.pub` +Finally, go to [http://gitlab.biologie.ens-lyon.fr/profile/keys](http://gitlab.biologie.ens-lyon.fr/profile/keys) and paste the content of the file `~/.ssh/id_rsa_gitlab_lbmc.pub` To test your connection run: @@ -119,721 +119,6 @@ ssh -Tv gitlab_lbmc **With this second method, you will have to replace every `https://gitlab.biologie.ens-lyon.fr/` url in the sequel with `gitlab_lbmc:`, the shortcut you defined in your `~/.ssh/config` file.** -# Part 1: Git alone +**[ Next**: Git Alone** ](./tp_1.md#part-1-git-alone)** -Git is a powerful tool to keep track of changes in your project and to manage your modifications history. -In this first part of the TP you will practice different git commands to keep track of your work and modifications with Git. -> A Git repository is an informatic project (folder) where changes are recorded using Git. - -## Creation of a git repository - -Start by creating a folder `alpha` in which you are going to write your project: - -```sh -mkdir alpha -cd alpha -``` - -Once in the alpha folder, you can initialize a Git repository. -A Git repository is a project tracked and indexed by git. - -```sh -git init -ls -la -``` - -> The `git init` command create a hidden `.git` folder at the root of your project. - -**You should not temper with the content of the `.git` folder.** -Everything in the `.git` folder belongs to Git the rest of the `alpha` folder belongs to you. - -When you issue `git` command the content of the `.git` folder is accessed or modified by git. - -## Using git to track changes - -There is nothing in our repository: - -```sh -git status -git st -``` - -We defined `st` as an alias of `status` in the `~/.gitconfig` file, so the two commands are equivalent. - -Our first code: - -```sh -mkdir data -git st -echo 'a' > data/letter.txt -git st -``` - -**Git doesn’t track folders, only files**. For git folders are just structures to organise files. -With the creation of `letter.txt` git is aware of a change in the repository. -There are **untracked files**. - -To start tracking files we use the command `git add` : - -```sh -git add data/letter.txt -ls -R .git/objects/ -git st -``` - -> `git add` greate **git blob**: -> -> - contains the compressed content of a file -> - The name of the blob is the [SHA1](https://en.wikipedia.org/wiki/SHA-1) of the file. -> - The first two characters of the [SHA1](https://en.wikipedia.org/wiki/SHA-1) are used as the name of a directory inside the objects folder -> - The rest of the hash is used as the name of the blob file - -There are now changes to be committed, this means that git is now following the state of the `data/letter.txt` file. -The current state of `data/letter.txt` is recorded. - - - -```sh -git ls-files --stage -echo "1234" > data/number.txt -git add data/number.txt -git ls-files --stage -printf "1" > data/number.txt -``` - -We changed the state of `data/number.txt`, but those changes are not staged to be committed. -The previous states of `data/number.txt` is still recorded *somewhere* even if it differs from its current state. - -> This *somewhere* is called the **staging area** (where you stage changes). - -```sh -git add data/number.txt -git ls-files --stage -``` - - - - - - -You can save the state of the staging area **definitively** with the command `git commit` - -```sh -git commit -m "a1" -git st -``` - -Here "a1" is the message associated with the commit. - -)](img/git_commit_xkcd.png) - -> There are two rules for committing: -> -> - Commit often -> - Write clear and informative logs -> [http://git-scm.com/book/ch5-2.html](http://git-scm.com/book/ch5-2.html) - -You cleared the changes to be committed and wrote them in a commit. - -```sh -git log -git lo -``` - -You wrote your first commit with a unique identifier: -`531019e7119268c4dae5ac44ef5929165794f4b0` - -> `git commit`: -> - creates a tree graph to represent the content of the version of the project being committed -> - creates a commit object -> - points the current branch to the new commit object - -```sh -git ls-tree -r 531019e7119268c4dae5ac44ef5929165794f4b0 -git ls-tree -d 531019e7119268c4dae5ac44ef5929165794f4b0 -``` - -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 - -# Part 2: Git remote - -We start by cloning an existing repository. -`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. - -```sh -cd ~/ -git clone https://gitlab.biologie.ens-lyon.fr/LBMC/file_handle.git git_basis_tp1 -cd git_basis_tp1 -ls -l -``` - -We can check the log (history) of this repository with the command `git log` -this command has a huge number of formatting options. - -```sh -git log --graph --all -git lt -``` - -Git history is not necessarily linear. The bifurcations or branches are a useful -tool to try and implement new things without tempering with the main (`master`) -branch of a project. - -To check the different branches of this project: - -```sh -git branch -``` - -By default the main branch and the first branch of a git repository is called `master`. -In the framework of this TP we want to start working from a specific point of the -`file_handle` project history. The sha1 of this commit is `727b007b`. - -```sh -git checkout 727b007b -``` - -We are now in a `detached HEAD state`. This means that the working area was set -to match the commit `727b007b` which is not pointed by any references. - -We are in part 1 or this TP so we want to setup a new branch to work on. -The command `git checkout -b <branch>` creates the branch `<branch>` and update -the working directory to match it. - -```sh -git checkout -b tp1 -ls -l -``` - -The content of the branch `tp1` is the same as the one of the commit `727b007b`. - -## Modification to Git history - -Gitlab is able to render the [markdown format](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) of files with the `.md` extension. -To enable this rendering for the `README` file, we need to rename it. To do this we have -two options: - -- Deleting the file and creating a new one with the commands `git rm README` and `git add README.md`. -- Directly renaming the file with the command `git mv README README.md`. - -```sh -git mv README README.md -``` - -Why did we choose `git mv` instead of the other option (besides entering less git commands)? - -The commands like `git mv` and `git rm` add the modification directly to the staging -area. - -```sh -git status # README.md is in the staging area -git commit -m "README: rename to README.md for md rendering" -git status # README.md is in the git repository -``` - -The first thing is to add a title to this `README.md` file. - -```sh -echo "# file_handle" > README.md # we add the name of the project in the README -git status # README.md is in the working area -git add README.md -git status # README.md is in the staging area -git commit -m "README.md: add title" -git status # README.md is in the git repository -``` - - - -We then add a small description. - -```sh -echo "smalll python software to handle dated file names" >> README.md -git status -git diff README.md -git add README.md -git commit -m "README: smalll description of the software" -``` - -We made a mistake in the last commit: there is a typo in the commit message and -we also wanted to delete the file `todo.txt`. The command `git commit --amend` -allows us to edit the last commit. - -```sh -git rm todo.txt -git status -git commit --amend -``` - - -## Setting up your git repository - -We made some changes to the local git repository. We want to make them available -on the gitlab server. The command `git push <repos>` send your latest -modifications to the remote repository defined as `<repos>`. The default remote -repository is called `origin` - -```sh -git push -``` - -You don’t have permission to write to this repository (if you want to contribute to the file_handle project you can ask me later). -To cope with this problem you are going to create your own remote repository for this project on the gitlab server. - -To do so, go to [http://gitlab.biologie.ens-lyon.fr/](http://gitlab.biologie.ens-lyon.fr/) and click on **new project**. -You can give a name to your project (we are going to use `git_basis` in the following commands). Click on **Create project**. -You end up on your project home page. - -The main information is in the **ssh** box containing a link to your -repository : - -`git@gitlab.biologie.ens-lyon.fr:<user_name>/git_basis.git`. - -with the https protocol we have: -`https://lmodolo@gitlab.biologie.ens-lyon.fr/<user_name>/git_basis.git` - -> 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 -this server. - -```sh -git remote add perso https://gitlab.biologie.ens-lyon.fr/<user_name>/git_basis.git -git remote -v -``` - -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) - -# Part 3: Git together -Branch management is at the heart of Git. -These powerful mechanisms will help you to work in collaboration with others. -For the last part of the TP you need to pair with someone else. We will refer to you as developer **W** and the other person as developer **C**. - -## Developer **W**: - -For **C** to be able to push to you repository, you need to grant him access. -The gitlab access control is repository or branch-based. -Go to the project **Settings**, tab and then to **Member**. -You can search **C** and give him a role. Here we will use the role **Master** so **C** has as many rights as **W**. -Click on **Add to project** to validate the changes. - -The idea behind a branch-based permission is to allow developers to work on a given branch of your repository while keeping others under your control. - -## Developer **C**: - -Clone **W**’s repository: - -```sh -git clone https://gitlab.biologie.ens-lyon.fr/<W_name>/git_basis.git git_basis_tp2 -git clone https://gitlab.biologie.ens-lyon.fr/<W_name>/git_basis.git git_basis_tp2 -cd git_basis_tp2 -git remote -v -git checkout -b tp2 -``` - -The only remote that **C**’s local repository knows is **W**’s remote. - -**C** adds a dependency section to `README.md` - -````md -## Dependencies -The only dependencies for file_handle.py are `python3` and the `argspaste` - -```sh -sudo install python3 pip3 -pip3 install argparse -``` -```` - -```sh -git add README.md -git commit -m "README.md: add dependencies description" -git status -``` - -Developer **C** is now ahead of `remote/master` by one commit. - -```sh -git push -``` - -The command is not working. -Git writes a useful message giving you the right command for this first push. - -## Developer **W**: - -Before starting to work on the `file_handle`, developer **W** want to get the last version of the project. - -```sh -git branch -git fetch perso -git status -git branch -``` - -**W** sees that a new `tp2` branch was created. - -```sh -git checkout tp2 -git branch -``` - -**W** wants to add a small help section to the `README.md`. - -````md -## Usage -To know how to use the `file_handle.py` script, enter the following command: - -```sh -file_handle.py --help -``` -```` - -```sh -git add README.md -git commit -m "README.md: add Usage section" -git status -``` - -## Developer **C**: - -While **W** is contributing to the redaction of the documentation, developer **C** continue to work on it: - -```sh -git fetch -git status -``` - -````sh -## Usage -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>`. -```` - -```sh -git add README.md -git commit -m "README.md: add -f option description" -git status -git push -```` - -## Developer **W**: - -```sh -git push -``` - -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: - -- Moving or removing files -- Stashing -- Tagging -- Cherry-Picking -- Rewriting history (interactive rebasing) -- Bisecting diff --git a/tp_1.md b/tp_1.md new file mode 100644 index 0000000000000000000000000000000000000000..6c977d2ed6834e81aba6dba8cc090f8bb062c097 --- /dev/null +++ b/tp_1.md @@ -0,0 +1,349 @@ +# Part 1: Git alone + +Git is a powerful tool to keep track of changes in your project and to manage your modifications history. +In this first part of the TP you will practice different git commands to keep track of your work and modifications with Git. + +> A Git repository is an informatic project (folder) where changes are recorded using Git. + +## Creation of a git repository + +Start by creating a folder `alpha` in which you are going to write your project: + +```sh +mkdir alpha +cd alpha +``` + +Once in the alpha folder, you can initialize a Git repository. +A Git repository is a project tracked and indexed by git. + +```sh +git init +ls -la +``` + +> The `git init` command create a hidden `.git` folder at the root of your project. + +**You should not temper with the content of the `.git` folder.** +Everything in the `.git` folder belongs to Git the rest of the `alpha` folder belongs to you. + +When you issue `git` command the content of the `.git` folder is accessed or modified by git. + +## Using git to track changes + +There is nothing in our repository: + +```sh +git status +git st +``` + +We defined `st` as an alias of `status` in the `~/.gitconfig` file, so the two commands are equivalent. + +Our first code: + +```sh +mkdir data +git st +echo 'a' > data/letter.txt +git st +``` + +**Git doesn’t track folders, only files**. For git folders are just structures to organise files. +With the creation of `letter.txt` git is aware of a change in the repository. +There are **untracked files**. + +To start tracking files we use the command `git add` : + +```sh +git add data/letter.txt +ls -R .git/objects/ +git st +``` + +> `git add` greate **git blob**: +> +> - contains the compressed content of a file +> - The name of the blob is the [SHA1](https://en.wikipedia.org/wiki/SHA-1) of the file. +> - The first two characters of the [SHA1](https://en.wikipedia.org/wiki/SHA-1) are used as the name of a directory inside the objects folder +> - The rest of the hash is used as the name of the blob file + +There are now changes to be committed, this means that git is now following the state of the `data/letter.txt` file. +The current state of `data/letter.txt` is recorded. + + + +```sh +git ls-files --stage +echo "1234" > data/number.txt +git add data/number.txt +git ls-files --stage +printf "1" > data/number.txt +``` + +We changed the state of `data/number.txt`, but those changes are not staged to be committed. +The previous states of `data/number.txt` is still recorded *somewhere* even if it differs from its current state. + +> This *somewhere* is called the **staging area** (where you stage changes). + +```sh +git add data/number.txt +git ls-files --stage +``` + + + + + + +You can save the state of the staging area **definitively** with the command `git commit` + +```sh +git commit -m "a1" +git st +``` + +Here "a1" is the message associated with the commit. + +)](img/git_commit_xkcd.png) + +> There are two rules for committing: +> +> - Commit often +> - Write clear and informative logs +> [http://git-scm.com/book/ch5-2.html](http://git-scm.com/book/ch5-2.html) + +You cleared the changes to be committed and wrote them in a commit. + +```sh +git log +git lo +``` + +You wrote your first commit with a unique identifier: +`531019e7119268c4dae5ac44ef5929165794f4b0` + +> `git commit`: +> - creates a tree graph to represent the content of the version of the project being committed +> - creates a commit object +> - points the current branch to the new commit object + +```sh +git ls-tree -r 531019e7119268c4dae5ac44ef5929165794f4b0 +git ls-tree -d 531019e7119268c4dae5ac44ef5929165794f4b0 +``` + +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 + +[ ****Next: Git remote**** ](./tp_2.md#part-2-git-remote) diff --git a/tp_2.md b/tp_2.md new file mode 100644 index 0000000000000000000000000000000000000000..22d52d096ff05c87f35a27b815511371e80be5ff --- /dev/null +++ b/tp_2.md @@ -0,0 +1,191 @@ +# Part 2: Git remote + +We start by cloning an existing repository. +`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. + +```sh +cd ~/ +git clone https://gitlab.biologie.ens-lyon.fr/LBMC/file_handle.git git_basis_tp1 +cd git_basis_tp1 +ls -l +``` + +We can check the log (history) of this repository with the command `git log` +this command has a huge number of formatting options. + +```sh +git log --graph --all +git lt +``` + +Git history is not necessarily linear. The bifurcations or branches are a useful +tool to try and implement new things without tempering with the main (`master`) +branch of a project. + +To check the different branches of this project: + +```sh +git branch +``` + +By default the main branch and the first branch of a git repository is called `master`. +In the framework of this TP we want to start working from a specific point of the +`file_handle` project history. The sha1 of this commit is `727b007b`. + +```sh +git checkout 727b007b +``` + +We are now in a `detached HEAD state`. This means that the working area was set +to match the commit `727b007b` which is not pointed by any references. + +We are in part 1 or this TP so we want to setup a new branch to work on. +The command `git checkout -b <branch>` creates the branch `<branch>` and update +the working directory to match it. + +```sh +git checkout -b tp1 +ls -l +``` + +The content of the branch `tp1` is the same as the one of the commit `727b007b`. + +## Modification to Git history + +Gitlab is able to render the [markdown format](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) of files with the `.md` extension. +To enable this rendering for the `README` file, we need to rename it. To do this we have +two options: + +- Deleting the file and creating a new one with the commands `git rm README` and `git add README.md`. +- Directly renaming the file with the command `git mv README README.md`. + +```sh +git mv README README.md +``` + +Why did we choose `git mv` instead of the other option (besides entering less git commands)? + +The commands like `git mv` and `git rm` add the modification directly to the staging +area. + +```sh +git status # README.md is in the staging area +git commit -m "README: rename to README.md for md rendering" +git status # README.md is in the git repository +``` + +The first thing is to add a title to this `README.md` file. + +```sh +echo "# file_handle" > README.md # we add the name of the project in the README +git status # README.md is in the working area +git add README.md +git status # README.md is in the staging area +git commit -m "README.md: add title" +git status # README.md is in the git repository +``` + + + +We then add a small description. + +```sh +echo "smalll python software to handle dated file names" >> README.md +git status +git diff README.md +git add README.md +git commit -m "README: smalll description of the software" +``` + +We made a mistake in the last commit: there is a typo in the commit message and +we also wanted to delete the file `todo.txt`. The command `git commit --amend` +allows us to edit the last commit. + +```sh +git rm todo.txt +git status +git commit --amend +``` + + +## Setting up your git repository + +We made some changes to the local git repository. We want to make them available +on the gitlab server. The command `git push <repos>` send your latest +modifications to the remote repository defined as `<repos>`. The default remote +repository is called `origin` + +```sh +git push +``` + +You don’t have permission to write to this repository (if you want to contribute to the file_handle project you can ask me later). +To cope with this problem you are going to create your own remote repository for this project on the gitlab server. + +To do so, go to [http://gitlab.biologie.ens-lyon.fr/](http://gitlab.biologie.ens-lyon.fr/) and click on **new project**. +You can give a name to your project (we are going to use `git_basis` in the following commands). Click on **Create project**. +You end up on your project home page. + +The main information is in the **ssh** box containing a link to your +repository : + +`git@gitlab.biologie.ens-lyon.fr:<user_name>/git_basis.git`. + +with the https protocol we have: +`https://lmodolo@gitlab.biologie.ens-lyon.fr/<user_name>/git_basis.git` + +> 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 +this server. + +```sh +git remote add perso https://gitlab.biologie.ens-lyon.fr/<user_name>/git_basis.git +git remote -v +``` + +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) + +[ ****Next: Git together**** ](./tp_3.md#part-3-git-together) diff --git a/tp_3.md b/tp_3.md new file mode 100644 index 0000000000000000000000000000000000000000..880bf7d039a369a91ea9cc34f6e31a3b3487c0fb --- /dev/null +++ b/tp_3.md @@ -0,0 +1,181 @@ +# Part 3: Git together + +Branch management is at the heart of Git. +These powerful mechanisms will help you to work in collaboration with others. +For the last part of the TP you need to pair with someone else. We will refer to you as developer **W** and the other person as developer **C**. + +## Developer **W**: + +For **C** to be able to push to you repository, you need to grant him access. +The gitlab access control is repository or branch-based. +Go to the project **Settings**, tab and then to **Member**. +You can search **C** and give him a role. Here we will use the role **Master** so **C** has as many rights as **W**. +Click on **Add to project** to validate the changes. + +The idea behind a branch-based permission is to allow developers to work on a given branch of your repository while keeping others under your control. + +## Developer **C**: + +Clone **W**’s repository: + +```sh +git clone https://gitlab.biologie.ens-lyon.fr/<W_name>/git_basis.git git_basis_tp2 +git clone https://gitlab.biologie.ens-lyon.fr/<W_name>/git_basis.git git_basis_tp2 +cd git_basis_tp2 +git remote -v +git checkout -b tp2 +``` + +The only remote that **C**’s local repository knows is **W**’s remote. + +**C** adds a dependency section to `README.md` + +````md +## Dependencies +The only dependencies for file_handle.py are `python3` and the `argspaste` + +```sh +sudo install python3 pip3 +pip3 install argparse +``` +```` + +```sh +git add README.md +git commit -m "README.md: add dependencies description" +git status +``` + +Developer **C** is now ahead of `remote/master` by one commit. + +```sh +git push +``` + +The command is not working. +Git writes a useful message giving you the right command for this first push. + +## Developer **W**: + +Before starting to work on the `file_handle`, developer **W** want to get the last version of the project. + +```sh +git branch +git fetch perso +git status +git branch +``` + +**W** sees that a new `tp2` branch was created. + +```sh +git checkout tp2 +git branch +``` + +**W** wants to add a small help section to the `README.md`. + +````md +## Usage +To know how to use the `file_handle.py` script, enter the following command: + +```sh +file_handle.py --help +``` +```` + +```sh +git add README.md +git commit -m "README.md: add Usage section" +git status +``` + +## Developer **C**: + +While **W** is contributing to the redaction of the documentation, developer **C** continue to work on it: + +```sh +git fetch +git status +``` + +````sh +## Usage +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>`. +```` + +```sh +git add README.md +git commit -m "README.md: add -f option description" +git status +git push +```` + +## Developer **W**: + +```sh +git push +``` + +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: + +- Moving or removing files +- Stashing +- Tagging +- Cherry-Picking +- Rewriting history (interactive rebasing) +- Bisecting