diff --git a/advanced/Exercise_1.md b/advanced/Exercise_1.md deleted file mode 100644 index 8f2e4b6..0000000 --- a/advanced/Exercise_1.md +++ /dev/null @@ -1,207 +0,0 @@ -# Exercise 1 - Examining your repository - -In this exercise, you will explore a few different techniques for examining a git repository and it's history, including git log, git diff, and git show. You will first clone the repository containing this git course, and then examine it using the various tools. The sections covering git log and git diff are adapted from the following Atlassian tutorials: - -https://www.atlassian.com/git/tutorials/git-log - -https://www.atlassian.com/git/tutorials/saving-changes/git-diff - -These tutorials offer a more comprehensive overview of the useful functionality of git log and git diff than presented here, so keep them in mind as a future reference. - -* [Clone the git repository](#initialization) - -* [Use git log](#log) - -* [Use git diff](#diff) - -* [Use git show](#show) - -## Clone the git repository - -```plaintext -git clone git@github.com:C2SM/git-course -``` - -Navigate into the repository. - -```plaintext -cd git-course -``` - -## Use git log to have a look at the repository - -The `git log` command lists the commits in the repository. You can use the various options for git log to format how the commits are displayed and/or filter which commits are displayed. Start with the basic command to see the default behavior. You can exit out of the log at any time by hitting the `q` key. - -```plaintext -git log -``` - -Let's look at some of the ways that we can change how the commits are displayed. - -To get a high-level overview of the repository, try the `--oneline` option: - -```plaintext -git log --oneline -``` - -To get a brief summary of the changes introduced by each commit, use the `--stat` option: - -```plaintext -git log --stat -``` - -To quickly see who has been working on what commits, use the `shortlog` command: - -```plaintext -git shortlog -``` - -To get a picture of the history of the branch structure of the repository, use the `--graph` option. This option is particularly helpful when used in combination with the `--oneline` option. - -```plaintext -git log --graph --oneline -``` - -Now, let's look at some of the ways we can filter commits using the `git log` options. - -To limit the number of commits displayed, try the `-` option: - -```plaintext -git log -3 -``` - -To see commits made by a certain author, use the `--author` option. This option accepts a regular expression and returns all commits whose author matches that pattern. - -```plaintext -git log --author="Jonas" -``` - -To see all the commits that changed one specific file, for example the `helpers.sh` file, try the following: - -```plaintext -git log helpers.sh -``` - -To see all commits that introduce or remove a specific line of text, for example `Have fun!`, try the following: - -```plaintext -git log -S 'Have fun!' -``` - -Remember that you can combine any of these git log options together to achieve your desired output. And if you decide on a format that you would like to use frequently, you can create an alias for this format using `git config`. For example, to set up an alias to use git log with the `--oneline` and `--graph` options, use the following command: - -```plaintext -git config --global alias.lg "log --oneline --graph" -``` - -Now, if you use `git lg`, you will see the log with the options you specified. Note that you can create aliases for any git command using `git config` and this is a very powerful tool. - - -## Use git diff -The `git diff` command shows the differences between two different git data sources. These data sources can be commits, files, branches, tags and more. The `git diff` command can be used from the command line, but it can be difficult to interpret the output in that format. Therefore people often use a third-party visualization tool to examine the output of git diff. In this section, you will start by using `git diff` from the command line and then you will explore some of the options available for improving the readability of the output. - -### git diff on the command line - -To get started, let's make a new branch with a change in it. - -```plaintext -git switch -c difftest -``` - -Open the README.md file and make a change in it. - -The default behavior of `git diff` is to show any uncommited changes since the last commit. Try this now. - -```plaintext -git diff -``` - -Now, let's add and commit the change you made. Remember to make a meaningful commit message. Note that the `-a` option to the `git commit` command allows us to add any changed files to the staging area without having to separately use the `git add` command. - -```plaintext -git commit -am "Put your commit message here" -``` - -You can use `git diff` to compare the content between branches, for example the main branch and the difftest branch: - -```plaintext -git diff main difftest -``` - -You can also output the difference between one specific file in two different branches. - -```plaintext -git diff main difftest ./README.md -``` - -Now let's use git diff to compare the difference between two commits. Use git log to get two commit IDs, and then put the two commit IDs as arguments to git diff. - -```plaintext -git log -``` - -```plaintext -git diff 8eb59b37 f435db79 -``` - -Here you can see that the output of git diff in the command line can be difficult to read if there are many changes. Let's have a look at some ways to better visualize these differences. - -### git diff visualization options - -#### git difftool - -One way that you can better visualize the output of `git diff` is to use `git difftool`. This command is a wrapper for `git diff` that allows you to specify the diff tool of your choice to view the output in. You can see all of the possible tools with the `--tool-help` option. - -```plaintext -git difftool --tool-help -``` - -Here you can see listed the available tools that are already installed on the system you are using, as well as the other tools that would work but you don't yet have installed. - -Choose one of the installed tools on your system, and try `git difftool`. Use the `-t` option to specify which tool you want to use. For example, to use vimdiff, try: - -```plaintext -git difftool -t vimdiff 8eb59b37 f435db79 -``` - -This command allows you to step through all the files that were changed between the two commits one at a time and get a clearer picture of how the files were changed. - -#### Git web interface - -Git web interfaces, such as Github and Gitlab, also have built in wrappers which help to visualize the output for `git diff`. - -Let's have a look at the git course repository on Github. You can find it here: -https://github.com/C2SM/git-course - -You can get to the `git diff` wrapper by adding `/compare` to any Github repository url. So have a look at: -https://github.com/C2SM/git-course/compare - -This will open up a comparison interface in your web browser. Here you can use the gui provided to compare the code between branches and forks. You can also specify exact comparisons by changing the url. For example, to compare the same two commits we have compared with `git diff` and `git difftool`, you can use the following url: - -https://github.com/C2SM/git-course/compare/8eb59b37..f435db79 - -You can find more information about how to use the Github compare tool [here](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/viewing-and-comparing-commits/comparing-commits). - -Note: You may have noticed that the comparison we have done includes some binary (.png) files. Because these are binary files, you cannot get an exact difference between them, but the fact that they showed up in the `git diff` output means that the files have changed between the two commits. This can sometimes be useful information. Remember that it's best practice to try to avoid committing binary files into git repositories when possible. If it is necessary, try to keep the size of the files as small as possible to make it quick and easy to work with your git repository. - -## Use git show - -The `git show` command is another command that can be used to examine git objects such as tags and commits. This command can be useful for examining commits because it shows not only the commit SHA and commit message like `git log` but additionally the difference in the files committed like `git diff`. - -Go back to your terminal window with the git course repository and try out the `git show` command. - -```plaintext -git show -``` - -By default, this command shows us the latest commit, or HEAD in git terminology. You can see the commit SHA and message as well as the difference between any files that were changed in this commit. You could examine any commit in the repository by giving the commit SHA as an input to the `git show` command. - -```plaintext -git show f435db79 -``` - -Like `git log`, `git show` can be used with various options that allow you to change the way the information is displayed. There are options that change the way the commit SHA and message are displayed, such as `git show --oneline`. There are also options that change the way that the diff is displayed, but none of them really alleviate the problem that big diffs are generally hard to read in the terminal window. As with all git commands, you can use the `-h` option to get a description of all the possible options that can be used with `git show`. - -```plaintext -git show -h -``` diff --git a/advanced/Exercise_1_git-log-diff-show.md b/advanced/Exercise_1_git-log-diff-show.md new file mode 100644 index 0000000..f7c2632 --- /dev/null +++ b/advanced/Exercise_1_git-log-diff-show.md @@ -0,0 +1,213 @@ +# Exercise 1 - Examining your repository + +In this exercise, you will explore several different techniques for examining a Git repository and its history, including `git log`, `git diff`, and `git show`. You will first clone the repository containing this Git course, and then examine it using the various tools. The `git log` and `git diff` sections are adapted from the following Atlassian tutorials: + +https://www.atlassian.com/git/tutorials/git-log + +https://www.atlassian.com/git/tutorials/saving-changes/git-diff + +These tutorials provide a more comprehensive overview of the useful features of `git log` and `git diff` than is presented here, so keep them in mind for future reference. + +* [Clone the Git repository](#initialization) + +* [Use git log](#log) + +* [Use git diff](#diff) + +* [Use git show](#show) + +## Clone the git repository + +```plaintext +git clone git@github.com:C2SM/git-course git-course +``` + +Navigate to the repository. + +```plaintext +cd git-course +``` + +## Use git log to have a look at the repository + +The `git log` command lists the commits in the repository. You can use the various options for `git log` to format how the commits are displayed and/or filter which commits are displayed. Start with the basic command to see the default behavior. You can exit out of the log at any time by pressing the `q` key. + +```plaintext +git log +``` + +Let's look at some options for changing the way commits are displayed. + +To get a high-level overview of the repository, try the `--oneline` option: + +```plaintext +git log --oneline +``` + +To get a brief summary of the changes made by each commit, use the `--stat` option: + +```plaintext +git log --stat +``` + +To quickly see who has worked on which commits, use the `shortlog` command: + +```plaintext +git shortlog +``` + +To get a picture of the history of the branch structure of the repository, use the `--graph` option. This is especially useful when used in combination with the `--oneline` option. + +```plaintext +git log --graph --oneline +``` + +Now, let's look at some of the ways we can filter commits using the `git log` options. + +To limit the number of commits shown, try the `-` option: + +```plaintext +git log -3 +``` + +To see commits made by a specific author, use the `--author` option. This option takes a regular expression and returns all commits whose author matches that pattern. + +```plaintext +git log --author="Jonas" +``` + +To see all the commits that have changed a specific file, such as *helpers.sh*, try the following: + +```plaintext +git log helpers.sh +``` + +To see all commits that add or remove a specific line of text, for example `Have fun!`, try the following: + +```plaintext +git log -S 'Have fun!' +``` + +In case you want to ignore case-sensitivity use the `-i` option: + +```plaintext +git log -i -S 'have fun!' +``` + +Remember that you can combine any of these `git log` options to get the output you want. And if you decide on a format that you want to use frequently, you can create an alias for that format using `git config`. For example, to set up an alias to use `git log` with the `--oneline` and `--graph` options, use the following command: + +```plaintext +git config --global alias.lg "log --oneline --graph" +``` + +This command edits a file with path `~/.gitconfig`. If you now run `git lg`, you will see the log with the options you specified. Note that you can create aliases for any Git command using `git config` and this is a very powerful tool. + + +## Use git diff +The `git diff` command shows the differences between two different Git data sources. These data sources can be commits, files, branches, tags and more. The `git diff` command can be used from the command line, but it can be difficult to interpret the output in that format. Therefore, people often use a third-party visualization tool to examine the output of `git diff`. In this section, you will first learn how to use `git diff` from the command line and then you will explore some of the options available to improve the readability of the output. + +### git diff on the command line + +To get started, let's make a new branch with one change in it. + +```plaintext +git switch -c difftest +``` + +Open the README.md file and make a change to it. + +The default behavior of `git diff` is to show all uncommited changes since the last commit. Try this now. + +```plaintext +git diff +``` + +Now, let's add and commit the change you made. Remember to write a meaningful commit message. Note that the `-a` option to the `git commit` command allows us to add any changed files to the staging area without having to use the `git add` command separately. + +```plaintext +git commit -am "Type your commit message here" +``` + +You can use `git diff` to compare the contents of branches, for example the main branch and the difftest branch: + +```plaintext +git diff main difftest +``` + +You can also output the difference between a given file in two different branches. + +```plaintext +git diff main difftest ./README.md +``` + +Now let's use `git diff` to compare the difference between two commits. Use `git log` to get two commit IDs, and then pass the two commit IDs as arguments to `git diff`. + +```plaintext +git log +``` + +```plaintext +git diff 8eb59b37 f435db79 +``` + +Here you can see that the output of `git diff` on the command line can be difficult to read when there are many changes. Let's have a look at some ways to better visualize these differences. + +### git diff visualization options + +#### git difftool + +One way to better visualize the output of `git diff` is to use `git difftool`. This command is a wrapper for `git diff` that allows you to specify the diff tool of your choice to view the output in. You can see all of the possible tools with the `--tool-help` option. + +```plaintext +git difftool --tool-help +``` + +This command lists the available tools that are already installed on the system you're using, as well as the other tools that would work but that you don't have installed yet. + +Choose one of the tools installed on your system, and try `git difftool`. Use the `-t` option to specify which tool you want to use. For example, to use vimdiff, try: + +```plaintext +git difftool -t vimdiff 8eb59b37 f435db79 +``` + +This command allows you to step through all the files that were changed between the two commits, one at a time, and get a clearer picture of how the files were changed. + +#### Git web interface + +Git web interfaces, such as GitHub and GitLab, also have built-in wrappers that help to visualize the output for `git diff`. + +Let's take a look at the Git course repository on GitHub. You can find it here: +https://github.com/C2SM/git-course + +You can access the `git diff` wrapper by adding `/compare` to any GitHub repository URL. So have a look at: +https://github.com/C2SM/git-course/compare + +This will open up a comparison interface in your web browser. Here you can use the GUI provided to compare the code between branches and forks. You can also specify exact comparisons by changing the URL. For example, to compare the same two commits that we compared with `git diff` and `git difftool`, you can use the following URL: + +https://github.com/C2SM/git-course/compare/8eb59b37..f435db79 + +You can find more information about using the GitHub compare tool [here](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/viewing-and-comparing-commits/comparing-commits). + +Note: You may have noticed that the comparison we did included some binary (.png) files. Since these are binary files, you cannot get an exact difference between them, but the fact that they showed up in the `git diff` output means that the files have changed between the two commits. This can sometimes be useful information. Keep in mind that it's best practice to try to avoid committing binaries to Git repositories if possible. If it is necessary, try to keep the size of the files as small as possible to keep working with your Git repository fast and easy. + +## Use git show + +The `git show` command is another command that can be used to examine Git objects such as tags and commits. This command can be useful for examining commits because it shows not only the commit SHA and commit message like `git log`, but also the difference in the committed files like the `git diff` command. + +Go back to your terminal window with the Git course repository and try out the `git show` command. + +```plaintext +git show +``` + +By default, this command shows us the latest commit, or HEAD in Git terminology. You can see the commit SHA and message, as well as the difference between all the files that were changed in that commit. You can examine any commit in the repository by passing the commit SHA as an input to the `git show` command. + +```plaintext +git show f435db79 +``` + +Like `git log`, `git show` can be used with various options that allow you to change the way the information is displayed. There are options that change the way the commit SHA and message are displayed, such as `git show --oneline`. There are also options that change the way that the diff is displayed, but none of them really alleviate the problem that large diffs are generally hard to read in the terminal window. As with all Git commands, you can use the `-h` option to get a description of all the possible options that can be used with `git show`. + +```plaintext +git show --help +``` diff --git a/advanced/Exercise_2.md b/advanced/Exercise_2_git-bisect.md similarity index 52% rename from advanced/Exercise_2.md rename to advanced/Exercise_2_git-bisect.md index 32337cc..5c742fa 100644 --- a/advanced/Exercise_2.md +++ b/advanced/Exercise_2_git-bisect.md @@ -1,6 +1,6 @@ # Exercise 2 - Using git bisect -In this exercise, you will use `git bisect` to pinpoint the exact commit in a repository where the code has broken. This tool is very useful for debugging. For this exercise, we will be using a publicly available `git bisect` example: https://github.com/bast/git-bisect-exercise. It consists of a git repository that contains a simple python script to calculate pi to 2 decimal places, which has broken at some point in the history of the repository. Your job is to use `git bisect` to find the commit where the code has broken and no longer returns the correct value of pi. You will do this in two ways: first, using `git bisect` manually, and then doing it automatically with `git bisect run`. Spoiler alert: Try to avoid the README.md file in the repository, as it contains the solution of the exercise. +In this exercise, you will use `git bisect` to pinpoint the exact commit in a repository where the code has broken. This tool is very useful for debugging. For this exercise, we will be using a publicly available `git bisect` example: https://github.com/bast/git-bisect-exercise. It consists of a Git repository that contains a simple Python script to calculate $\pi$ to 2 decimal places, which has broken at some point in the history of the repository. Your job is to use `git bisect` to find the commit where the code has broken and no longer returns the correct value of $\pi$. You will do this in two ways: first, using `git bisect` manually, and then doing it automatically with `git bisect run`. Spoiler alert: Try to avoid the *README.md* file in the repository, as it contains the solution of the exercise. * [Clone and test the example repository](#clone) @@ -10,10 +10,10 @@ In this exercise, you will use `git bisect` to pinpoint the exact commit in a re ## Clone and test the example repository -Clone the example repository into it's own folder. +Clone the example repository into its own folder (outside the *git-course* folder). ```plaintext -git clone git@github.com:bast/git-bisect-exercise +git clone git@github.com:bast/git-bisect-exercise git-bisect-exercise ``` Navigate into the repository. @@ -22,27 +22,27 @@ Navigate into the repository. cd git-bisect-exercise ``` -Test the pi calculating script (`get_pi.py`) to see what value of pi it gives. +Test the $\pi$ calculating script (`get_pi.py`) to see what value of $\pi$ it gives. ```plaintext python get_pi.py ``` -The script gives 3.57 as a result. To be correct it should give 3.14. +The script gives 3.57 as a result. To be correct it should give 3.14. -Let's test the first commit in the repository to see if the script was working then. First, we need to find the hash for the first commit using git log. You can list the commits starting with the oldest using the `--reverse` flag. +Let's test the first commit in the repository to see if the script was working then. First, we need to find the hash for the first commit using `git log`. You can list the commits starting with the oldest using the `--reverse` flag. ```plaintext git log --reverse ``` -Note the SHA value of the first commit in the repository, then use `q` to exit the log. +Note the SHA value of the first commit in the repository, then use `q` to exit the log. -Switch to the first commit in the repository. +Switch to the first commit in the repository. The `--detach` option of `git switch` sets the HEAD to the specified commit, you can always undo this switch with `git switch -`. For older versions of Git, where `git switch` is not yet implemented, use `git checkout f0ea950` instead. ```plaintext -git checkout f0ea950 +git switch --detach f0ea950 ``` -Test the script again. +Test the script again. ```plaintext python get_pi.py @@ -50,7 +50,7 @@ python get_pi.py Now we get the correct answer: 3.14. So we know that somewhere between the first commit and the last commit, the script has stopped working. Git bisect will help us to figure out at exactly which commit this happened. -Before we move on, let's switch our repository back to the final commit. +Before we move on, let's switch our repository back to the final commit. ```plaintext git switch - @@ -58,47 +58,47 @@ git switch - ## Use git bisect manually to find the bad commit -Initiate a git bisect session. +Initiate a `git bisect` session. ```plaintext git bisect start ``` -Next, you need to tell git bisect the commit you know where the code is good, and the commit you know where the code is bad. If you omit the commit SHA number, then git assumes you are referring to the current commit. +Next, you need to tell `git bisect` the commit you know where the code is good, and the commit you know where the code is bad. If you omit the commit SHA number, then Git assumes you are referring to the current commit. -Tell git the current commit is bad. +Tell Git that the current commit is bad. ```plaintext git bisect bad ``` -Tell git the first commit is good. +Tell Git that the first commit is good. ```plaintext git bisect good f0ea950 ``` -Once you have run this command, git has enough information to start the bisection. It automatically finds the commit that is halfway in between the good commit and the bad commit, and checks it out for you. All you need to do is test the current commit, and then tell git whether the code is good or bad at this point. +Once you have run this command, Git has enough information to start the bisection. It automatically finds the commit that is halfway in between the good commit and the bad commit, and switches to it. All you need to do is test the current commit, and then tell Git whether the code is good or bad at that point. ```plaintext python get_pi.py ``` -In this first case, you should see that the code gives 3.57, which is the incorrect answer. Let's inform git of this. +In this first case, you should see that the code gives 3.57, which is the incorrect answer. Let's tell Git about this. ```plaintext git bisect bad ``` -Once you run this command, git will recalculate the halfway point between the new good and bad commits and check out a new commit for you to test. Continue by testing the script using `python get_pi.py` and then telling git whether the commit gives the correct result (`git bisect good`), or the incorrect result (`git bisect bad`). Keep repeating this process until you get a message from git identifying the exact commit where the code breaks. You can check the correct solution below. +Once you run this command, Git will recalculate the halfway point between the new good and bad commits and check out a new commit for you to test. Continue by testing the script using `python get_pi.py` and then telling Git whether the commit gives the correct result (`git bisect good`), or the incorrect result (`git bisect bad`). Keep repeating this process until you get a message from Git identifying the exact commit where the code breaks. You can check the correct solution below.
Click here to see the solution - The code breaks on commit number 137. + The code breaks at commit number 137.
-You should reset the repository to it's original state before you try any other git commands. +You should reset the repository to its original state before you try any other Git commands. ```plaintext git bisect reset @@ -106,7 +106,7 @@ git bisect reset ## Use git bisect run to automatically find the bad commit -We can also automate this process to make it easier. We just need a testing script that will return 0 if the code is correct, and an error value between 1 and 127 (excluding 125) if the code is incorrect. The error value 125 is reserved for when the code cannot be tested, and tells git bisect to skip the current commit. You could use whatever language you like to write such a script. If you are so inclined, you can try to write such a script yourself now. If not, you can use the python script provided below. If you do so, make sure you read through the python script so that you understand what it does. +We can also automate this process to make it easier. We just need a testing script that will return 0 if the code is correct, and an error value between 1 and 127 (excluding 125) if the code is incorrect. The error value 125 is reserved for when the code cannot be tested, and tells `git bisect` to skip the current commit. You could use whatever language you like to write such a script. If you are so inclined, you can try to write such a script yourself now. If not, you can use the Python script provided below. If you do so, make sure you read through the Python script so that you understand what it does.
Click here to see contents of the code checking script @@ -126,30 +126,30 @@ We can also automate this process to make it easier. We just need a testing scri ```
-Now that we have a script to check the code, let's use git bisect run to quickly find the bad commit in our repository. +Now that we have a script to check the code, let's use `git bisect run` to quickly find the bad commit in our repository. -Start a new git bisect session. +Start a new `git bisect` session. ```plaintext git bisect start ``` -Tell git that the code is broken in the current commit. +Tell Git that the code is broken in the current commit. ```plaintext git bisect bad ``` -Tell git that the code works in the first commit. +Tell Git that the code works in the first commit. ```plaintext git bisect good f0ea950 ``` -Use your checking script to automate the bisection process. Substitute the name of your checking script and the method for running it, if it is not a python script. +Use your checking script to automate the bisection process. Substitute the name of your checking script and the method for running it, if it is not a Python script. ```plaintext git bisect run python check_script.py ``` -Git bisect will automatically run through all the commits and test them until it finds the first bad commit, which it will report to you. Remember to use `git bisect reset` to get the repository back to it's original state. +Git bisect will automatically run through all the commits and test them until it finds the first bad commit, which it will report to you. Remember to use `git bisect reset` to get the repository back to its original state. diff --git a/advanced/Exercise_3.md b/advanced/Exercise_3.md deleted file mode 100644 index 23ec027..0000000 --- a/advanced/Exercise_3.md +++ /dev/null @@ -1,112 +0,0 @@ -# Exercise 3 - Ignoring files - -In this exercise, you will first use a provided script to generate a simple git repository containing materials for planning a conference. You will then create a README file for the conference planning repository using the Markdown language. Then you will generate an HTML README file, and finally create a `.gitignore` file for the repository. This exercise is closely adapted from the [OESA Git Workshop](https://oesa.pages.ufz.de/git-exercises/exercise-5.html). - -* [Initialize the git repository](#initialize) - -* [Create a README file](#readme) - -* [Generate the README file in HTML](#html) - -* [Create a .gitignore file](#gitignore) - -## Initialize the git repository - -Use the [helper scripts](helpers.sh) provided in folder [advanced](../advanced) to set up a simple git repository. - -First, clone the git-course repository if you have not already done so in Exercise 1. - -```plaintext -git clone git@github.com:C2SM/git-course -``` - -Navigate into the repository. - -```plaintext -cd git-course -``` - -Set the name of the default branch in any git repository you create to be `main`. - -```plaintext -git config --global init.defaultBranch main -``` - -Source the file containing the helper scripts: `helpers.sh` - -```plaintext -cd advanced -source helpers.sh -``` -Run the `init_advanced_repo` script. This script will create a folder at the same level as the git-course repository containing a simple git repository called `conference_planning`. - -```plaintext -init_advanced_repo -``` - -Take some time to familiarize yourself with the git repository by examining the files and using `git status`, `git log`, `git diff`, etc. - -## Create a README file - -Create a README.md file in the `conference_planning` folder. - -```plaintext -touch README.md -``` - -Put some content in the README file using a file editor. Good README file content could include the title of the project, a description of the project, how to use the project, and/or the contributors of the project. The `.md` file extension we have used indicates that the README file will be written using the Markdown language, which is a common format for README files because it displays well in web browsers. [Here](https://www.markdownguide.org/basic-syntax/) are some tips for using the Markdown language. - -Now commit the README file to the repository. - -```plaintext -git add README.md -git commit -m "Add README file" -``` -## Generate the README file in HTML - -It may be useful to convert the README file into an html file in order to see how it will look to a user web browsing your repository. We will use a document converter called [Pandoc](https://pandoc.org) to do this. You can check if you have Pandoc installed with the following command: - -```plaintext -pandoc -h -``` - -If you don't have Pandoc installed, there are instructions on how to do so [here](https://pandoc.org/installing.html). - -Once you have Pandoc ready to go, convert the README to an html file. - -```plaintext -pandoc README.md -o README.html -``` - -You can examine the output html file in a browser to check how it looks. - -We could now commit the `README.html` file. However, it is good practice not to commit anything to a repository that can be generated from the project's source files. Therefore, we will instead tell git to ignore this file. - -Before we do that, let's check the status of the repository, and ensure that the html file you generated is unstaged. - -```plaintext -git status -``` - -## Create a .gitignore file - -In order to tell git to ignore our html file, we will create a `.gitignore` file. - -```plaintext -touch .gitignore -``` - -Open the file using a file editor. In this file, you can list files, directories, or file patterns to be ignored, one entry per line. In order to ignore the html file, you can either list it specifically (`README.html`), or use wildcards to tell git to ignore all html files (`*.html`). - -Check the status again. - -```plaintext -git status -``` - -The html file has disappeared, and now the `.gitignore` file is listed as unstaged. In order to save the file in the repository, commit it. - -```plaintext -git add .gitignore -git commit -m "Added gitignore file to ignore html files" -``` diff --git a/advanced/Exercise_3_gitignore.md b/advanced/Exercise_3_gitignore.md new file mode 100644 index 0000000..60de010 --- /dev/null +++ b/advanced/Exercise_3_gitignore.md @@ -0,0 +1,113 @@ +# Exercise 3 - Ignoring files + +In this exercise, you will first use a provided script to generate a simple Git repository containing materials for planning a conference. You will then create a *README* file for the so-called *conference_planning* repository using the Markdown language. Then you will generate an HTML README file, and finally create a *.gitignore* file for the repository. This exercise is closely adapted from the [OESA Git Workshop](https://oesa.pages.ufz.de/git-exercises/exercise-5.html). + +* [Initialize the Git repository](#initialize) + +* [Create a README file](#readme) + +* [Generate the README file in HTML](#html) + +* [Create a .gitignore file](#gitignore) + +## Initialize the Git repository + +Use the [helper script](helpers.sh) provided in the [advanced](../advanced) folder to set up a simple Git repository. + +First, clone the *git-course* repository if you have not already done so in Exercise 1. + +```plaintext +git clone git@github.com:C2SM/git-course git-course +``` + +Navigate into the repository. + +```plaintext +cd git-course +``` + +Set the name of the default branch in any Git repository you create to be `main`. + +```plaintext +git config --global init.defaultBranch main +``` + +Source the file containing the helper functions: *helpers.sh + +```plaintext +cd advanced +source helpers.sh +``` +Run the *init_advanced_repo* function. This will create a folder at the same level as the *git-course* repository containing a simple Git repository called *conference_planning*. + +```plaintext +init_advanced_repo +``` + +Take some time to familiarize yourself with the Git repository by examining the files and using `git status`, `git log`, `git diff`, etc. + +## Create a README file + +Create a *README.md* file in the *conference_planning* folder. + +```plaintext +touch README.md +``` + +Put some content in the *README* file using a file editor. Good *README* file content could include the title of the project, a description of the project, how to use the project, and/or the contributors to the project. The *.md* file extension we have used indicates that the *README* file will be written using the Markdown language, which is a common format for *README* files because it displays well in web browsers. [Here](https://www.markdownguide.org/basic-syntax/) are some tips for using the Markdown language. + +Now commit the *README* file to the repository. + +```plaintext +git add README.md +git commit -m "Add README file" +``` +## Generate the README file in HTML + +It may be useful to convert the *README* file to HTML in order to see how it will look to a user browsing your repository on the web. We will use a document converter called [Pandoc](https://pandoc.org) to do this. +If you don't have Pandoc installed, there are instructions on how to do so [here](https://pandoc.org/installing.html). If you use conda, then `conda install -c conda-forge pandoc` should do the trick. + +You can check if Pandoc is installed correctly by running the following command: + +```plaintext +pandoc -h +``` + +Once you have Pandoc up and running, convert the *README* to an HTML file. + +```plaintext +pandoc README.md -o README.html +``` + +You can examine the output HTML file in a browser to check how it looks. + +We could now commit the *README.html* file. However, it is good practice not to commit anything to a repository that can be generated from the project's source code. Instead, we will tell Git to ignore this file. + +Before we do that, let's check the status of the repository, and ensure that the HTML file you generated is unstaged. + +```plaintext +git status +``` + +## Create a .gitignore file + +In order to tell Git to ignore our HTML file, we will create a *.gitignore* file. + +```plaintext +touch .gitignore +``` + +Open the file using a file editor. In this file, you can list files, directories, or file patterns to be ignored, one entry per line. In order to ignore the HTML file, you can either list it specifically (*README.html*), or use wildcards to tell Git to ignore all HTML files (*.\*html)*. + +Check the status again. + +```plaintext +git status +``` + +The HTML file has disappeared, and now the *.gitignore* file is listed as unstaged. In order to save the file in the repository, commit it. + +```plaintext +git add .gitignore +git commit -m "Added gitignore file to ignore html files" +``` diff --git a/advanced/Exercise_4.md b/advanced/Exercise_4.md deleted file mode 100644 index e55f9db..0000000 --- a/advanced/Exercise_4.md +++ /dev/null @@ -1,82 +0,0 @@ -# Exercise 4 - Using git stash and git worktree - -In this exercise, you will learn how to use `git stash` to save changes not yet ready to be committed. Then you will learn how to recover those changes in your git repository. Next you will use `git worktree` to learn how to work with simultaneous checkouts of the same repository in one place, allowing you work on and transfer files between different git branches easily. - -This exercise uses the same git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the `Initialize the git repository` section [here](./Exercise_3.md). - -* [Stash your changes](#stash) - -* [Use git worktree to create parallel branch checkouts](#worktree) - -## Stash your changes - -Let's make a change to the repository by adding a conference breakfast to the schedule on day 1. The following are examples of how to use the `sed` command line tool, which were tested on Linux but may not work on other platforms. You can also simply open the file in a file editor to make the change. - -```plaintext -sed -i '/Daily/ a 08:30-09:00: Conference breakfast' schedule_day1 -``` - -Now let's suppose that you decide that you aren't ready to commit this change, but you don't want to discard it either. Use `git stash` to save the change and revert the repository back the latest commit. - -```plaintext -git stash save "Add breakfast to day 1" -``` - -If you check the status of your repository now, you can see that the change you made is no longer listed as unstaged. - -```plaintext -git status -``` - -You can save more than one stash if you like. Examine the list of your stashes (currently just the one you just created). - -```plaintext -git stash list -``` - -Let's assume you have now decided you would like to recover these changes and keep working with them. Let's recover the stash using it's identifier from the list (`stash@{0}`). - -```plaintext -git stash pop stash@{0} -``` - -Note that you can make any changes or commits in between saving the stash and reapplying it to your repository. If there are conflicts between the stash and the new commits in your repository, you will need to resolve those conflicts manually before proceeding, and a merge commit will be generated. You should also know that the stash is only saved in your local repository copy and cannot be pushed to a remote repository to be used by other people. - -## Use git worktree to create parallel branch checkouts - -Next you will use `git worktree` to checkout multiple instances of the git repository in parallel. This can be very useful for transferring changes between branches or working on different features simultaneously. - -In order to use `git worktree`, you must work in a bare git repository. Remember that a bare git repository is one where there is no working directory. Instead it just consists of the files and objects git uses to register the changes you make to your working directory. - -Let's make a bare clone of the conference_planning git repository. - -```plaintext -cd .. -git clone --bare conference_planning conference_bare -``` - -Navigate into the new repository and examine it. - -```plaintext -cd conference_bare -ls -git status -``` - -Note that the `git status` command does not work because we are not in a working directory! - -Let's make a folder containing the files as they currently are in the main branch of our repository. - -```plaintext -git worktree add main -``` - -A folder called `main` has been created, and if you examine it you will find the checked out files from the main branch. You can make changes and add and commit them as you normally would from this new folder. - -Let's suppose that in addition to working in the main branch of the repository, you would also like to work in a feature branch in parallel. You can do this easily now. Let's add a feature branch. - -```plaintext -git worktree add feature -``` - -Because the branch `feature` did not already exist, one has been created from the main branch. It is now located in the `feature` folder, and you can now navigate there and work as you normally would in your git working directory. Note that you can also push and fetch commits as you normally would to and from remote repositories if you need to. diff --git a/advanced/Exercise_4_git-stash-worktree.md b/advanced/Exercise_4_git-stash-worktree.md new file mode 100644 index 0000000..ed7fe7a --- /dev/null +++ b/advanced/Exercise_4_git-stash-worktree.md @@ -0,0 +1,82 @@ +# Exercise 4 - Using git stash and git worktree + +In this exercise, you will learn how to use `git stash` to store changes that are not yet ready for commit. Then you will learn how to recover those changes in your Git repository. Next, you will use `git worktree` to learn how to work with simultaneous checkouts of the same repository in one place, allowing you work on and transfer files between different Git branches easily. + +This exercise uses the same Git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the [Initialize the Git repository](./Exercise_3_gitignore.md#initialize) section of Exercise 3. + +* [Stash your changes](#stash) + +* [Use git worktree to create parallel branch checkouts](#worktree) + +## Stash your changes + +Let's make a change to the repository by adding a conference breakfast to the schedule on day 1. The following command is an example of how to use the `sed` command line tool, which was tested on **Linux** but may not work on other platforms, i.e. **MacOS**. It will add '08:30-09:00: Conference breakfast' after the line containing the word 'Daily' in *schedule_day1.txt*. If this does not work on your platform, simply open the file in a file editor to make the change. + +```plaintext +sed -i '/Daily/ a 08:30-09:00: Conference breakfast' schedule_day1.txt +``` + +Now let's suppose that you decide that you aren't ready to commit this change, but you don't want to discard it either. Use `git stash` to store the change and revert the repository back to the last commit. + +```plaintext +git stash save "Add breakfast to day 1" +``` + +If you check the status of your repository now, you will see that the change you made is no longer listed as unstaged. + +```plaintext +git status +``` + +You can save more than one stash if you like. Examine the list of your stashes (currently only the one you just created). + +```plaintext +git stash list +``` + +Let's assume you have now decided you would like to recover these changes and keep working with them. Let's recover the stash using its identifier from the list (`stash@{0}`). + +```plaintext +git stash pop stash@{0} +``` + +Note that you can make any changes or commits in between saving the stash and reapplying it to your repository. If there are conflicts between the stash and the new commits in your repository, you will need to resolve those conflicts manually before proceeding, and a merge commit will be generated. You should also know that the stash is only stored in your local copy of the repository, and cannot be pushed to a remote repository to be used by other people. + +## Use git worktree to create parallel branch checkouts + +Now you will use `git worktree` to checkout multiple instances of the Git repository in parallel. This can be very useful for transferring changes between branches, or working on different features simultaneously. + +In order to use `git worktree`, you must work in a bare Git repository. A bare Git repository is one where there is no working directory. Instead, it consists only of the files and objects that Git uses to register the changes you make to your working directories. This can be a lot of information we don't care about and we therefore recommend you do hide it in a hidden folder called *.bare*. + +We will first create a new folder *conference_worktree* and then make a bare clone of the *conference_planning* Git repository into it. The relevant information for Git will be hidden in the *.bare* folder, so the *conference_worktree* folder will seem emtpy to you. + +```plaintext +cd .. +mkdir conference_worktree +cd conference_worktree +git clone --bare ../conference_planning .bare +``` + +To now make this repository a Git repository, we need to copy the relevant information into the *.git* file: + +```plaintext +echo "gitdir: ./.bare" > .git +``` + +See what happens if you type `git status`. Why does it not work? + +Let's make a folder containing the files as they currently are in the *main* branch of our repository. + +```plaintext +git worktree add main +``` + +A folder called *main* has been created, and if you examine it you will find the files checked out from the *main* branch (within this folder `git status` should work again!). You can make changes and add and commit them as you normally would from a Git folder. + +Let's suppose that in addition to working on the *main* branch of the repository, you also want to work on a parallel *feature* branch. You can do this easily now. Let's add a *feature* branch (make sure to do this from the parent folder and not from a work tree). + +```plaintext +git worktree add feature +``` + +Since the *feature* branch did not already exist, one has been created from the *main* branch. It is now located in the *feature* folder, and you can now navigate there and work as you normally would in your Git working directory. Note that you can also push and fetch commits to and from remote repositories as you would in a normal Git working directory. diff --git a/advanced/Exercise_5.md b/advanced/Exercise_5.md deleted file mode 100644 index 2ac58e2..0000000 --- a/advanced/Exercise_5.md +++ /dev/null @@ -1,107 +0,0 @@ -# Exercise 5 - Using git rebase - -In this exercise, we will learn to use `git rebase` to rewrite the history of a feature branch in order to keep the history of the main branch cleaner by avoiding merge commits. First we will use the merge strategy to add a feature to a main branch that is being simultaneously developed. Then we will use the rebase strategy to do the same thing and compare the differences. - -This exercise uses the same git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the ["Initialize the git repository" section of Exercise 3](./Exercise_3.md#initialize). - -* [Use the merge strategy to incorporate a change into a moving main branch](#merge) - -* [Use the rebase strategy to incorporate a change into a moving main branch](#rebase) - -## Use the merge strategy to incorporate a change into a moving main branch - -Navigate to the `conference_planning` folder. - -Create and switch to a new feature branch. - -```plaintext -git switch -c merge_feature -``` - -Make a change to the schedule for day 2. Let's add a presentation session. The following are examples of how to use the `sed` command line tool, which were tested on Linux but may not work on other platforms. You can also simply open the file in a file editor to make the change. - -```plaintext -sed -i '/Coffee/ a 11:15-12:30: Presentation session' schedule_day2 -``` - -Add and commit this change. - -```plaintext -git commit -am "Add presentation session to day 2" -``` - -Switch back to the main branch and make a change to the day 2 schedule there. Let's add a dinner break. - -```plaintext -git switch main -sed -i '/Evening/ i Dinner break' schedule_day2 -``` - -Add and commit this change. - -```plaintext -git commit -am "Add dinner break to day 2" -``` -Now you are ready to incorporate the changes you made in your feature branch into the main branch. Let's do this with a merge. - -```plaintext -git merge merge_feature -``` - -Examine the log. You should see that a merge commit has been created in the main branch. - -Follow git best practices and delete the no longer needed feature branch. - -```plaintext -git branch -d merge_feature -``` - -## Use the rebase strategy to incorporate a change into a moving main branch - -Create and switch to a new feature branch. - -```plaintext -git switch -c rebase_feature -``` - -Make a change to the schedule for day 2. Let's add a lunch break. - -```plaintext -sed -i '/Presentation/ a 12:30-13:30: Lunch break' schedule_day2 -``` - -Add and commit this change. - -```plaintext -git commit -am "Add lunch break to day 2" -``` - -Switch back to the main branch and make a change to the day 2 schedule there. Let's add an apero before dinner. - -```plaintext -git switch main -sed -i '/Dinner/ i Apero' schedule_day2 -``` - -Add and commit this change. - -```plaintext -git commit -am "Add Apero to day 2" -``` - -Now you are ready to incorporate the changes you made in your feature branch into the main branch. Let's do this with rebase this time instead of a merge. - -```plaintext -git rebase main rebase_feature -``` - -Examine the repository status and log. Git has switched us to the `rebase_feature` branch and played the commit from the main branch here, without creating a merge commit. - -Now, switch to the `main` branch and sync it with the `rebase_feature` branch. - -```plaintext -git switch main -git merge rebase_feature -``` - -Examine the repository status and log again. Even though we have done a merge command, by doing the rebase beforehand we have created a situation where the merge can be done with the fast-forward technique, and therefore no merge commit was required. This is particularly advantageous in actively developed codes because it allows the history of the main branch to remain clean and free of unnecessary merge commits. diff --git a/advanced/Exercise_5_git-rebase.md b/advanced/Exercise_5_git-rebase.md new file mode 100644 index 0000000..a63723f --- /dev/null +++ b/advanced/Exercise_5_git-rebase.md @@ -0,0 +1,113 @@ +# Exercise 5 - Using git rebase + +In this exercise, we will learn how to use `git rebase` to rewrite the history of a feature branch in order to keep the history of the *main* branch cleaner by avoiding merge commits. First, we will use the merge strategy to add a feature to a *main* branch that is being simultaneously developed. Then we will use the rebase strategy to do the same thing and compare the differences. + +This exercise uses the same Git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the [Initialize the Git repository](./Exercise_3_gitignore.md#initialize) section of Exercise 3. + +* [Use the merge strategy to incorporate a change into a moving main branch](#merge) + +* [Use the rebase strategy to incorporate a change into a moving main branch](#rebase) + +## Use the merge strategy to incorporate a change into a moving main branch + +Navigate to the *conference_planning* folder. + +There could be modifications in the repository still from Exercise 4. +Restore the repository to the last commit in history to avoid problems later on. +```plaintext +git checkout -- . +``` + +Create and switch to a new feature branch. + +```plaintext +git switch -c merge_feature +``` + +Make a change to the schedule for day 2. Let's add a presentation session after the coffee break. The following are examples of how to use the `sed` command line tool, which were tested on **Linux** but may not work on other platforms, i.e. **MacOS**. You can also simply open the file in a file editor to make the change. + +```plaintext +sed -i '/Coffee/ a 11:15-12:30: Presentation session' schedule_day2.txt +``` + +Add and commit this change. + +```plaintext +git commit -am "Add presentation session to day 2" +``` + +Switch back to the *main* branch and make a change to the day 2 schedule there. Let's add a dinner as an evening activity. + +```plaintext +git switch main +sed -i '/Evening/ i Dinner' schedule_day2.txt +``` + +Add and commit this change. + +```plaintext +git commit -am "Add dinner to day 2" +``` +Now you are ready to incorporate the changes you made on your feature branch into the *main* branch. Let's do this with a merge. + +```plaintext +git merge merge_feature +``` + +Examine the log. You should see that a merge commit has been created in the *main* branch. + +Follow Git best practices and delete the no longer needed feature branch. + +```plaintext +git branch -d merge_feature +``` + +## Use the rebase strategy to incorporate a change into a moving main branch + +Create and switch to a new feature branch. + +```plaintext +git switch -c rebase_feature +``` + +Make a change to the schedule for day 2. Let's add a lunch break. + +```plaintext +sed -i '/Presentation/ a 12:30-13:30: Lunch break' schedule_day2.txt +``` + +Add and commit this change. + +```plaintext +git commit -am "Add lunch break to day 2" +``` + +Switch back to the *main* branch and make a change to the day 2 schedule there. Let's add an apero before dinner. + +```plaintext +git switch main +sed -i '/Dinner/ i Apero' schedule_day2.txt +``` + +Add and commit this change. + +```plaintext +git commit -am "Add Apero to day 2" +``` + +Now you are ready to incorporate the changes you made on your feature branch into the *main* branch. This time we'll do it with a rebase instead of a merge. + +```plaintext +git rebase main rebase_feature +``` + +Examine the repository status and log. Git has switched us to the *rebase_feature* branch and played the commit from the *main* branch here, without creating a merge commit. + +Now, switch to the *main* branch and sync it with the *rebase_feature* branch. + +```plaintext +git switch main +git merge rebase_feature +``` + +Examine the repository status and log again. Even though we did a merge command, by doing the rebase beforehand, we have created a situation where the merge can be done using the fast-forward technique, and therefore no merge commit was required. This is particularly advantageous in actively developed codes because it allows the history of the *main* branch to remain clean and free of unnecessary merge commits. diff --git a/advanced/Exercise_6.md b/advanced/Exercise_6.md deleted file mode 100644 index a6a7e1e..0000000 --- a/advanced/Exercise_6.md +++ /dev/null @@ -1,62 +0,0 @@ -# Exercise 6 - Using git cherry-pick - -In this exercise, we will learn to use git to cherry pick a commit. We will add a series of commits to a feature branch, and then use cherry pick to apply only one of these commits to the main branch. - -This exercise uses the same git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the ["Initialize the git repository" section of Exercise 3](./Exercise_3.md#initialize). - -* [Add feature branch and commits](#feature) - -* [Use git cherry-pick](#cherry) - -## Add feature branch and commits - -Navigate to the `conference_planning` folder. - -Add a feature branch. - -```plaintext -git switch -c cherry_feature -``` - -Let's add a couple of commits to this branch. - -Add a keynote speech to the schedule for day 1. You can use a file editor to open the file, or use a command line tool to change the file. The following gives examples using the `sed` command line tool, which were tested on Linux but may not work on other platforms. - -```plaintext -sed -i '/^Daily/a 08:00-09:00: Keynote speech' schedule_day1 -``` - -Add and commit this change. Remember to use a meaningful commit message. - -```plaintext -git commit -am "Add keynote speech to day 1" -``` - -Add an excursion to the schedule for day 2, and add and commit this change as well. - -```plaintext -sed -i '/^12:30/a 13:30-15:00: Excursion' schedule_day2 -git commit -am "Add excursion to day 2" -``` - -Extend the coffee break on day 1 to be half an hour in length. Add and commit this change. - -```plaintext -sed -i '/Coffee/c\11:00-11:30: Coffee break' schedule_day1 -git commit -am "Extend coffee break on day 1" -``` - -Use git log to have a look at the history. Make a note of the SHA of the commit you just made. - -## Use git cherry-pick - -Switch to the main branch, and cherry-pick the last commit, substituting the SHA of the commit you just made for `` in the following commands. - -```plaintext -git switch main -git cherry-pick -``` - -Have a look at the repository using the log, and examine the files as well. There's a couple important things to note here. First, notice that git has created an entirely new commit and SHA for the commit you cherry picked. This means that the feature branch should NOT be merged into the main branch anymore, because you will end up with two commits with exactly the same content. Therefore, cherry picking should really be reserved for saving useful changes from abandoned branches. If the branch is still actively being developed, then `git merge` should be used instead. - -The other important thing to notice here is that git has only applied the changes in the last commit, i.e. the extension of the coffee break. The other changes we made before in previous commits (adding the keynote and excursion) are not applied. diff --git a/advanced/Exercise_6_git-cherry-pick.md b/advanced/Exercise_6_git-cherry-pick.md new file mode 100644 index 0000000..d808099 --- /dev/null +++ b/advanced/Exercise_6_git-cherry-pick.md @@ -0,0 +1,62 @@ +# Exercise 6 - Using git cherry-pick + +In this exercise, we will learn how to use Git to cherry pick a commit. We will add a series of commits to a feature branch, and then use cherry pick to apply only one of those commits to the *main* branch. + +This exercise uses the same Git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the [Initialize the Git repository](./Exercise_3_gitignore.md#initialize) section of Exercise 3. + +* [Add feature branch and commits](#feature) + +* [Use git cherry-pick](#cherry) + +## Add feature branch and commits + +Navigate to the *conference_planning* folder. + +Add a feature branch. + +```plaintext +git switch -c cherry_feature +``` + +Let's add a couple of commits to this branch. + +Add a keynote speech to the schedule for day 1. You can use a file editor to open the file, or you can use a command-line tool to modify the file. The following are examples using the `sed` command line tool, which were tested on Linux, but may not work on other platforms. If you use the `sed` command line tool, make sure the changes have been added to the files. + +```plaintext +sed -i '/^Daily/a 08:00-09:00: Keynote speech' schedule_day1.txt +``` + +Add and commit this change. Remember to use a meaningful commit message. + +```plaintext +git commit -am "Add keynote speech to day 1" +``` + +Add an excursion to the schedule for day 2, and add and commit this change as well. + +```plaintext +sed -i '/^12:30/a 13:30-15:00: Excursion' schedule_day2.txt +git commit -am "Add excursion to day 2" +``` + +Extend the coffee break on day 1 to be half an hour in length. Add and commit this change. + +```plaintext +sed -i '/Coffee/c\11:00-11:30: Coffee break' schedule_day1.txt +git commit -am "Extend coffee break on day 1" +``` + +Use `git log` to have a look at the history. Make a note of the SHA of the commit you just made. + +## Use git cherry-pick + +Switch to the *main* branch, and cherry-pick the last commit, replacing `` with the SHA of the commit you just made in the following commands. + +```plaintext +git switch main +git cherry-pick +``` + +Have a look at the repository using the log, and examine the files as well. There's a couple important things to note here. First, notice that Git has created an entirely new commit and SHA for the commit you cherry picked. This means that the feature branch should NOT be merged into the *main* branch anymore, because you will end up with two commits with exactly the same content. Therefore, cherry picking should really be reserved for saving useful changes from abandoned branches. If the branch is still actively being developed, then `git merge` should be used instead. + +The other important thing to notice here is that Git has only applied the changes in the last commit, i.e. the extension of the coffee break. The other changes we made before in previous commits (adding the keynote and excursion) are not applied. diff --git a/advanced/Exercise_7.md b/advanced/Exercise_7.md deleted file mode 100644 index 42f9648..0000000 --- a/advanced/Exercise_7.md +++ /dev/null @@ -1,154 +0,0 @@ -# Exercise 7 - Using git submodule - -This exercise is designed to be paired with Exercise 8 to help you compare and contrast the two main methods for embedding a git repository into another git repository. This exercise illustrates the submodule method, while the next exercise illustrates the subtree method. In this exercise, we will learn to use git submodule to nest a git repository inside another one. We will first add the git submodule and examine how the host and nested repositories deal with changes in their respective files. We will then learn how to pull and push changes to and from the sub-repository. - -This exercise uses the same git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the ["Initialize the git repository" section of Exercise 3](./Exercise_3.md#initialize). - -* [Fork a repository on Github and add it as a submodule](#submodule) - -* [Examine how git deals with changes to both repositories](#examine) - -* [Create new content locally and update the sub-repository](#push) - -* [Create new content in the sub-repository and update the local repository](#pull) - -## Fork a repository on Github and add it as a submodule - -Navigate to the folder containing the `conference_planning` folder; in other words you should be in a folder that does not contain a git repository. Make a copy of the conference planning repository to use for adding the submodule. - -```plaintext -cp -r conference_planning conference_submodule -``` - -I have already created a repository on Github that we will use as a submodule. This repository is called `posters` and will contain the poster schedule for our conference. - -Navigate to the repository, found [here](https://github.com/kosterried/posters), and make a fork of it using the Github user interface. - -Let's add this fork as a submodule to our conference planning repository. You will need to copy the SSH address of your fork and paste it into the `git submodule add` command below. - -```plaintext -cd conference_submodule -git submodule add YOUR_FORK_ADDRESS -``` - -Note that Github requires an SSH key in order to push content to repositories. If you have not already set up an SSH key in your Github account, it is easy to do and you can find instructions [here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account). - -Check the status of the repository. - -```plaintext -git status -``` - -The output shows that there are some changes to the repository, and they are already staged for commit. We should commit them to finalize the adding of the submodule. - -```plaintext -git commit -m "Add the posters submodule" -``` - -Note that the `.gitmodules` file has been added, which contains the path of the submodule in the host repository and the address where the submodule is hosted which is the Github URL in our case. It could also be another git web host, a file path, or anywhere else a repository is hosted. - -Check the status of the submodule. - -```plaintext -git submodule status -``` - -The output shows us the SHA of the commit that the submodule is currently pointing to. - -## Examine how git deals with changes to both repositories - -Let's make some changes in both the host repository and the submodule to understand how git deals with submodules. - -Start by making a change in the host repository. Let's add a lunch break to the schedule on day 1. The following gives examples using the `sed` command line tool, which were tested on Linux but may not work on other platforms. You can also simply open the file in a file editor to make the change. - - -```plaintext -sed -i '/^11:00/a 12:00-13:00: Lunch break' schedule_day1 -``` - -Check the status of the repository. - -```plaintext -git status -``` - -You should see the change you just made listed as not staged for commit. - -Now navigate into the submodule and check the status there. - -```plaintext -cd posters -git status -``` - -Here we see that there are no changes. The submodule is treated as a completely separate repository with it's own staging area and commits. - -Now try making a change inside the submodule. Let's add a poster title to the poster schedule. - -```plaintext -echo "Poster 1: Git submodules and you" >> schedule -``` - -Check the status of the posters repository. - -```plaintext -git status -``` - -Check the status of the conference planning repository. - -```plaintext -cd .. -git status -``` - -Git is now informing us that we now have modified content in the posters submodule. - -## Create new content locally and update the sub-repository -Now, let's commit the change to the posters submodule, and push that change to our posters repository on Github. - -Go back into the posters submodule and add and commit the change we just made. - -```plaintext -cd posters -git commit -am "Add poster 1 to the schedule" -``` - -You can treat the submodule like any git repository and simply push the new commit to your fork on Github. - -```plaintext -git push origin -``` - -If you navigate back to your Github fork (and refresh the page if necessary), you should see the commit that you just made. - -The conference planning repository now needs to be updated, to point to the new commit in the posters submodule. Let's do this now. - -```plaintext -cd .. -git add posters -git commit -m "Update posters submodule" -``` - -Now, if you check the submodule status, you will see that it is pointing to the latest commit you made. - -## Create new content in the sub-repository and update the local repository - -Finally, let's learn how to pull changes from the submodule into our host repository. - -Navigate back to your fork of the poster repository on Github, and make a change to the schedule file and commit it. You can do this directly on the web interface by simply selecting the file and using the edit button. - -Once you have done this, go to back to the terminal and use `git submodule update` to get the main repository to fetch the new commit of the poster repository. - -```plaintext -git submodule update --remote --merge -``` - -The `--remote` option tells git to refer to the remote repository for the latest commit, in this case our poster repository. The `--merge` option tells git to merge the commit into our submodule to keep it up to date. - -In order to finalize the update, we need to commit it to the main repository. - -```plaintext -git add posters -git commit -am "Update posters to latest commit" -``` diff --git a/advanced/Exercise_7_git-hooks.md b/advanced/Exercise_7_git-hooks.md new file mode 100644 index 0000000..fc9fddc --- /dev/null +++ b/advanced/Exercise_7_git-hooks.md @@ -0,0 +1,148 @@ +# Exercise 7 - Custom Git Hooks + +In this exercise, you will practice implementing a pre-commit hook in the *conference_planning* repository to prevent committing files with trailing whitespace. You will also learn how to set up multiple pre-commit hooks for different tasks. + +This exercise uses the same Git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the [Initialize the Git repository](./Exercise_3_gitignore.md#initialize) section of Exercise 3. + +* [Implement Pre-Commit Hook for Trailing Whitespace](#whitespace) + +* [Test the Hook](#test) + +* [Add Another Custom Hook](#another) + +* [Local Testing with the `pre-commit` Tool](#pre-commit) + +* [Conclusion](#conclusion) + +## Implement Pre-Commit Hook for Trailing Whitespace + +As our first hook, we are going to implement a check for trailing whitespace. Trailing whitespaces are spaces or tabs at the end of a line in a text file, and they should be avoided because they can introduce inconsistencies in code formatting, create visual distractions, and cause unintended issues when working with the code. + +Open a terminal and navigate to the *conference_planning* repository on your local machine. Create a new file called *pre-commit* in the *.git/hooks* directory. Our Git hook files need to be set as executable in order to work. To do this, we use the `chmod` command to change file permissions, along with the `+x` parameter to make a file executable so that it can be run as a script. + +```sh +touch .git/hooks/pre-commit +chmod +x .git/hooks/pre-commit +``` + +Open the *pre-commit* file in a text editor and add the following script: + +```bash +#!/bin/bash + +# This is the pre-commit hook to prevent committing files with trailing whitespace. + +# Redirect output to stderr. +exec 1>&2 + +# Check for trailing whitespace in staged files. +if git diff --check --cached | grep -q '[[:blank:]]$'; then + echo "Error: Found files with trailing whitespace." + echo "Please remove trailing whitespace before committing." + exit 1 +fi +``` + +Save and close the file. + +## Test the Hook + +Now you have a pre-commit hook for preventing trailing whitespace set up. + +Create a new branch or make changes on an existing branch and stage your changes using `git add`. + +Try to make a commit with a file that has trailing whitespace and observe how the *pre-commit-whitespace* hook prevents the commit. + +## Add Another Custom Hook + +The following repository contains a collection of useful Git Hooks: https://github.com/CompSciLauren/awesome-git-hooks + +We now want to implement another *pre-commit* in addition to the trailing whitespace test. + +To do this, we will first rename our existing *pre-commit* script: + +```sh +mv .git/hooks/pre-commit .git/hooks/pre-commit-whitespace +``` + +Now, *pre-commit* becomes our master script that calls our actual hook scripts. + +```sh +touch .git/hooks/pre-commit +chmod +x .git/hooks/pre-commit +``` + +Integrate another *pre-commit* hook from the above repository into your workflow. Try the *verify-name-and-email* one if you are not sure where to start. In that case, your *.git/hooks/pre-commit* script should look as follows: + +```bash +#!/bin/bash + +# This is the main pre-commit hook script. + +# Run the whitespace check script. +.git/hooks/pre-commit-whitespace + +# Run the name and email verification script. +.git/hooks/pre-commit-verify-name-and-email +``` + +> **Hint:** Don't forget that all scripts need to be executable! + +Finally, verify that both *pre-commit* hooks are working correctly. + +## Local Testing with the `pre-commit` Tool + +In order to manually run the pre-commit hooks to preview your actions without committing, you can utilize the [pre-commit](https://pre-commit.com/) tool. + +If you haven't already, install the `pre-commit` tool globally on your system: + +```sh +pip install pre-commit +``` + +or + +```sh +conda install -c conda-forge pre-commit +``` + +After installation, you can verify that pre-commit is available by running: + +```sh +pre-commit --version +``` + +This should display the version of `pre-commit`, confirming a successful installation. + +In your *conference_planning* repository, create a *.pre-commit-config.yaml* file to configure which hooks to run. Here is an example configuration: + +```yaml +repos: +- repo: local + hooks: + - id: pre-commit-whitespace + name: check for trailing whitespaces + entry: .git/hooks/pre-commit-whitespace + language: system + # Add other hooks here if needed +``` + +This configuration specifies that the `pre-commit-whitespace` hook (the one we created earlier) should run. + +To manually run the `pre-commit` checks without making a commit, keep in mind that the `pre-commit` tool only checks against +staged files, i.e. you need to do `git add` for your file that contains whitespace. Afterwards, use the following command: + +```sh +pre-commit run --all-files --verbose +``` + +- `--all-files`: This flag tells `pre-commit` to check all files in the repository. +- `--verbose`: This flag provides detailed output, showing you exactly what each hook is doing. + +Running this command will execute the specified hooks, including your `pre-commit-whitespace` hook, and display the results. + +Examine the output of the `pre-commit` checks to see if any issues are reported. If the `pre-commit-whitespace` hook detects trailing whitespace, it will be shown in the output. + +## Conclusion + +In this exercise, you learned how to implement a *pre-commit* hook that prevents committing files with trailing whitespace. You also explored setting up multiple *pre-commit* hooks for different tasks. By integrating the `pre-commit` tool and configuring it with your custom hooks, you have learned a convenient way to check your changes before committing them, helping to maintain code quality and consistency in your development workflow. diff --git a/advanced/Exercise_8.md b/advanced/Exercise_8.md deleted file mode 100644 index 603adac..0000000 --- a/advanced/Exercise_8.md +++ /dev/null @@ -1,140 +0,0 @@ -# Exercise 8 - Using git subtree - -This exercise is designed to be paired with Exercise 7 to help you compare and contrast the two main methods for embedding a git repository into another git repository. In this exercise, we will learn to use `git subtree` to nest a git repository inside another one. We will first add the git subtree and examine how the host and nested repositories deal with changes in their respective files. We will then learn how to pull and push changes to and from the sub-repository. - -This exercise uses the same git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the ["Initialize the git repository" section of Exercise 3](./Exercise_3.md#initialize). - -* [Add the posters repository using git subtree](#subtree) - -* [Examine how git deals with changes to both repositories](#examine) - -* [Create new content locally and update the sub-repository](#push) - -* [Create new content in the sub-repository and update the local repository](#pull) - -## Add the posters repository using git subtree - -Navigate to the folder containing the `conference_planning` folder; in other words you should be in a folder that does not contain a git repository. Make a copy of the conference planning repository to use for adding the subtree. - -```plaintext -cp -r conference_planning conference_subtree -``` - -Let's add your `posters` Github fork we created in Exercise 7 as a subtree to our conference planning repository. - -```plaintext -cd conference_subtree -git subtree add --prefix posters YOUR_FORK_ADDRESS main --squash -``` - -> **_Note:_** If you get an error message of the type `Working tree has modifications. Cannot add.`, please first try `git switch main`. If the error still persists, type `git reset --hard`. For more information about this, check [this stackoverflow question](https://stackoverflow.com/questions/3623351/git-subtree-pull-says-that-the-working-tree-has-modifications-but-git-status-sa). - -The `--prefix` option gives a folder name relative to the root of the parent repository where the subtree will be installed. And the `--squash` option squashes the history of the posters repository into one commit in the parent repository. - -Check the status of the repository. - -```plaintext -git status -``` - -In this case, unlike the submodule, we don't have to make a commit to finalize the addition of the subtree. If you have a look at the log, you will see that git has added a couple of commits automatically to do this. - -```plaintext -git log -``` - -Note that there is no equivalent command to `git submodule status` that will allow us to list our subtrees and their status. - - -## Examine how git deals with changes to both repositories - -Let's make some changes in both the host repository and the subtree to understand how git deals with subtrees. - -Start by making a change in the host repository. Let's add a presentation session to the schedule on day 1. The following gives examples using the `sed` command line tool, which were tested on Linux but may not work on other platforms. You can also simply open the file in a file editor to make the change. - -```plaintext -sed -i '/^11:00/a 11:30-12:30: Presentation session' schedule_day1 -``` - -Check the status of the repository. - -```plaintext -git status -``` - -You should see the change you just made listed as not staged for commit. - -Now navigate into the subtree and check the status there. - -```plaintext -cd posters -git status -``` - -Here we see the same change listed as not staged for commit. This is a difference to the behavior we saw with submodules. With git subtrees, git considers both the host and nested repository to have the same staging area. The commits from the subtree are all put directly into the commit list of the host repository, unlike with `git submodule` where they are kept completely separate. - -Now try making a change inside the submodule. Let's add another poster title to the poster schedule. - -```plaintext -echo "Poster 3: 3 easy steps to git mastery" >> schedule -``` - -Check the status of the repository. - -```plaintext -git status -``` - -Now we see both changes listed as not staged for commit. This means that we could potentially now make a commit that included content from the host repository AND the subtree, and git would allow it. This could create problems with the history of the repository further down the line, so this should be avoided. The user simply needs to know not to do this, as git will not do anything to stop this. - -## Create new content locally and update the sub-repository - -Let's push the change we've made to the subtree to the Github fork. -First we need to commit this change. - -```plaintext -git add schedule -git commit -m "Add Poster 3" -``` - -Now, we need to go to the root of the host repository and use `git subtree push` to send this commit to our Github fork. - -```plaintext -cd .. -git subtree push --prefix=posters YOUR_FORK_ADDRESS main -``` - -If you check your Github fork now, you should see that the change has appeared there. - -## Create new content in the sub-repository and update the local repository - -Finally, let's learn how to pull changes from the subtree into our host repository. - -Navigate back to your fork of the poster repository on Github, and make a change to the schedule file and commit it. You can do this directly on the web interface by simply selecting the file and using the edit button. - -Let's update the main repository with the new content of the poster repository. -You can't do this if there are any changes in your working tree, so you should discard the changes we made to the day 1 schedule first. - -```plaintext -git restore schedule_day1 -``` - -Use `git subtree pull` to get the newest commit from your Github fork. - -```plaintext -git subtree pull --prefix posters YOUR_FORK_ADDRESS main --squash -``` - -Git will prompt you to enter a merge commit message, because it is treating this new information addition as a merge. - -Look at the contents of the posters subtree to see that the change you made has been added. - -```plaintext -cat posters/schedule -``` - -Have a look at the log to see exactly how git has handled the subtree and it's updates. - -```plaintext -git log -``` diff --git a/advanced/Exercise_8_git-submodule.md b/advanced/Exercise_8_git-submodule.md new file mode 100644 index 0000000..27da92d --- /dev/null +++ b/advanced/Exercise_8_git-submodule.md @@ -0,0 +1,154 @@ +# Exercise 8 - Using git submodule + +In this exercise, we will learn to use `git submodule` to nest a Git repository inside another one. We will first add the Git submodule and examine how the host and nested repositories deal with changes in their respective files. We will then learn how to pull and push changes to and from the sub-repository. + +This exercise uses the same Git repository that was created in Exercise 3. If you have not already done so, you can create it by following the instructions in the [Initialize the Git repository](./Exercise_3_gitignore.md#initialize) section of Exercise 3. + +* [Fork a repository on GitHub and add it as a submodule](#submodule) + +* [Examine how Git deals with changes to both repositories](#examine) + +* [Create new content locally and update the sub-repository](#push) + +* [Create new content in the sub-repository and update the local repository](#pull) + +## Fork a repository on GitHub and add it as a submodule + +Navigate to the folder that contains the *conference_planning* folder; in other words, you should be in a folder that does not contain a Git repository. Make a copy of the *conference_planning* repository, which you will use to add the submodule. + +```plaintext +cp -r conference_planning conference_submodule +``` + +We have created a repository on GitHub that you can use as a submodule. This repository is called *posters* and will contain the poster titles for our conference. + +Navigate to the [posters](https://github.com/AnnikaLau/posters) repository and create a fork of it using the GitHub user interface. + +Let's add this fork to our *conference_planning* repository as a submodule. You will need to copy the SSH address of your fork and paste it into the `git submodule add` command below. + +```plaintext +cd conference_submodule +git submodule add YOUR_FORK_ADDRESS posters +``` + +Note that GitHub requires an SSH key to push content to repositories. If you do not already have an SSH key set up in your GitHub account, follow the instructions for [Adding a new SSH key to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account). + +Check the status of your repository. + +```plaintext +git status +``` + +The output shows that there are some changes in the repository, and they are already staged for commit. We should commit them to complete the addition of the submodule. + +```plaintext +git commit -m "Add the posters submodule" +``` + +Note that the *.gitmodules* file has been added, which contains the path to the submodule in the host repository and the address where the submodule is hosted, which in our case is the GitHub URL. It could also be another Git web host, a file path, or anywhere else a repository is hosted. + +Check the status of the submodule. + +```plaintext +git submodule status +``` + +The output shows us the SHA of the commit that the submodule is currently pointing to. + +## Examine how Git deals with changes to both repositories + +Let's make some changes to both the host repository and the submodule to understand how Git handles submodules. + +Start with a change in the host repository. Let's add a lunch break to the schedule on day 1. The following is an example using the `sed` command line tool, which was tested on Linux but may not work on other platforms. You can also simply open the file in a file editor to make the change. + + +```plaintext +sed -i '/^11:00/a 12:00-13:00: Lunch break' schedule_day1.txt +``` + +Check the status of the repository. + +```plaintext +git status +``` + +You should see the change you just made listed as not staged for commit. + +Now navigate into the submodule and check the status there. + +```plaintext +cd posters +git status +``` + +Here we see that there are no changes. The submodule is treated as a completely separate repository, with its own staging area and commits. + +Now try to make a change inside the submodule. Let's add a poster title to the poster file. + +```plaintext +echo "Poster 1: Git submodules and you" >> posters.txt +``` + +Check the status of the *posters* repository. + +```plaintext +git status +``` + +Check the status of the *conference_planning* repository. + +```plaintext +cd .. +git status +``` + +Git is now informing us that we now have modified content in the *posters* submodule. + +## Create new content locally and update the sub-repository +Now, let's commit the change to the *posters* submodule, and push that change to our *posters* repository on GitHub. + +Go back into the *posters* submodule and add and commit the change we just made. + +```plaintext +cd posters +git commit -am "Add poster 1 to the schedule" +``` + +You can treat the submodule like any other Git repository, and simply push the new commit to your fork on GitHub. + +```plaintext +git push origin +``` + +If you go back to your GitHub fork (and refresh the page if necessary), you should see the commit that you just made. + +The *conference_planning* repository needs to be updated, to point to the new commit in the *posters* submodule. Let's do that now. + +```plaintext +cd .. +git add posters +git commit -m "Update posters submodule" +``` + +Now, if you check the status of the submodule, you will see that it points to the last commit you made. + +## Create new content in the sub-repository and update the local repository + +Finally, let's learn how to pull changes from the submodule into our host repository. + +Navigate back to your fork of the *posters* repository on GitHub, and make a change to the schedule file, and commit it. You can do this directly in the web interface by simply selecting the file and using the edit button. + +Once you have done this, go to back to the terminal and use `git submodule update` to get the main repository to fetch the new commit from the *posters* repository. + +```plaintext +git submodule update --remote --merge +``` + +The `--remote` option tells Git to refer to the remote repository for the latest commit, in this case our *posters* repository. The `--merge` option tells Git to merge the commit into our submodule to keep it up-to-date. + +To complete the update, we need to commit it to the main repository. + +```plaintext +git add posters +git commit -am "Update posters to latest commit" +``` diff --git a/advanced/examples/schedule_day1 b/advanced/examples/schedule_day1.txt similarity index 100% rename from advanced/examples/schedule_day1 rename to advanced/examples/schedule_day1.txt diff --git a/advanced/examples/schedule_day2 b/advanced/examples/schedule_day2.txt similarity index 100% rename from advanced/examples/schedule_day2 rename to advanced/examples/schedule_day2.txt diff --git a/advanced/helpers.sh b/advanced/helpers.sh index 0e35020..e9c408a 100755 --- a/advanced/helpers.sh +++ b/advanced/helpers.sh @@ -1,23 +1,25 @@ #!/bin/bash +script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + init_advanced_repo () { - mkdir ../../advanced_git - cd ../../advanced_git + mkdir $script_dir/../../advanced_git + cd $script_dir/../../advanced_git mkdir -p conference_planning cd conference_planning git init - cp ../../git-course/advanced/examples/schedule_day1 . - cp ../../git-course/advanced/examples/schedule_day2 . + cp $script_dir/examples/schedule_day1.txt . + cp $script_dir/examples/schedule_day2.txt . - git add schedule_day1 && git commit -m "Add schedule_day1" - git add schedule_day2 && git commit -m "Add schedule_day2" + git add schedule_day1.txt && git commit -m "Add schedule_day1" + git add schedule_day2.txt && git commit -m "Add schedule_day2" - ed -s schedule_day1 <<< $'/program/\na\n09:00-11:00: Poster session\n.\nw\nq' > /dev/null - ed -s schedule_day2 <<< $'/program/\na\n09:00-11:00: Poster session\n.\nw\nq' > /dev/null + ed -s schedule_day1.txt <<< $'/program/\na\n09:00-11:00: Poster session\n.\nw\nq' > /dev/null + ed -s schedule_day2.txt <<< $'/program/\na\n09:00-11:00: Poster session\n.\nw\nq' > /dev/null git add * && git commit -m "Add poster sessions in the morning" - ed -s schedule_day1 <<< $'/session/\na\n11:00-11:15: Coffee break\n.\nw\nq' > /dev/null - ed -s schedule_day2 <<< $'/session/\na\n11:00-11:15: Coffee break\n.\nw\nq' > /dev/null + ed -s schedule_day1.txt <<< $'/session/\na\n11:00-11:15: Coffee break\n.\nw\nq' > /dev/null + ed -s schedule_day2.txt <<< $'/session/\na\n11:00-11:15: Coffee break\n.\nw\nq' > /dev/null git add * && git commit -m "Add coffee break" git branch -m main diff --git a/advanced/schedule.md b/advanced/schedule.md new file mode 100644 index 0000000..f3826e1 --- /dev/null +++ b/advanced/schedule.md @@ -0,0 +1,14 @@ +## Schedule + +| Description | Presenter | Extent | Time est. | Time needed ('23) | Start time | End time | +| ------------------------- | --------- | --------- | --------- | ----------------- | ---------- | -------- | +| Welcome + Outline | Michael | 2 slides | | | | | +| Part 0 - Slides | Michael | 4 slides | | | | | +| Part 1 - Slides | | 5 slides | | | | | +| Part 1 - Exercises 1-2 | | | 21 min | | | | +| Part 2 - Slides + Demo | | 13 slides | | | | | +| Part 2 - Exercises 3-7 | | | 30 min | | | | +| Coffee break | | 1 coffee | | | | | +| Part 3 - Slides | | 9 slides | | | | | +| Part 3 - Exercise 8 | | | 12 min | | | | +| Part 4 - Slides + Demo | Michael | 4 slides | | | | |