diff --git a/README.md b/README.md index 3d64007..f099f76 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,7 @@ To run this course on your computer, the following things need to be set up: 1. [Git](#1-installing-git-on-your-computer) 2. [SSH key linked to your GitHub account](#2-creating-a-github-account-and-ssh-key) 3. [Python](#3-installing-python) -4. [JupyterLab](#4-installing-jupyterlab-beginners-course-only) (Beginner's course only) -5. [Final check](#5-final-check-advanced-course-only) (Advanced course only) +4. [Final check](#4-final-check) ### 1. Installing Git on your Computer @@ -51,92 +50,28 @@ Having a GitHub account allows you to collaborate on open-source projects and st #### Instructions - [Create your own GitHub account](https://github.com/) (if not yet available) -- [Generate an SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent). -- [Add your SSH key to GitHub](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account). - +- [Generate an SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) +- [Add your SSH key to GitHub](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account) ### 3. Installing Python To install Python, we recommend the [instructions from Real Python](https://realpython.com/installing-python/), but of course many other instructions will do as well. -### 4. Installing JupyterLab (Beginner's Course only) - -For the beginners course, you also need some non-standard Python packages, namely: - - jupyterlab - - bash_kernel - -To install these two packages, run the following commands in your terminal. - -If you have set up your SSH key, clone this Git repository by using the SSH protocol: -```bash -git clone git@github.com:C2SM/git-course.git -``` - -Otherwise, use the HTTPS protocol: -```bash -git clone https://github.com/C2SM/git-course.git -``` - -Navigate into the cloned repository: -```bash -cd git-course -``` - -Create a new Python virtual environment named *git-course_env*: -```bash -python -m venv git-course_env -``` - -Activate the newly created virtual environment: -```bash -source git-course_env/bin/activate -``` - -Install the required Python packages specified in the *requirements.txt* file: -```bash -pip install -r requirements.txt -``` - -Install Bash kernel for Jupyter notebooks: -```bash -python -m bash_kernel.install -``` - -To be able to access directories outside of the *git-course* repository in JupyterLab, you need to navigate out of the repository BEFORE launching JupyterLab: -``` -cd .. -``` - -Finally, you can start with the exercises by running: -``` -jupyter lab -``` -This command will open the JupyterLab interface in your browser. -If it does not open automatically, you will need to copy and paste the URL manually. -In this case, please follow the instructions on your terminal. - -If you are not able to start JupyterLab for some reason, you can try to launch a Jupyter Notebook, which provides a simpler user interface: -``` -jupyter notebook -``` - -### 5. Final check (Advanced course only) +### 4. Final check Check if everything is set up correctly by following the steps below from a Linux shell. -- Step 1: Download the file [check_requirements_advanced.sh](https://github.com/C2SM/git-course/blob/main/check_requirements_advanced.sh). +- Step 1: Download the file [check_requirements.sh](https://github.com/C2SM/git-course/blob/main/check_requirements.sh). ``` -curl -O https://raw.githubusercontent.com/C2SM/git-course/main/check_requirements_advanced.sh +curl -O https://raw.githubusercontent.com/C2SM/git-course/main/check_requirements.sh ``` - Step 2: Make the file executable. ``` -chmod +x ./check_requirements_advanced.sh +chmod +x ./check_requirements.sh ``` - Step 3: Run the script from a Linux shell. ``` -./check_requirements_advanced.sh +./check_requirements.sh ``` - **Have fun!** - diff --git a/beginner/Exercise_1/Exercise_1.ipynb b/beginner/Exercise_1/Exercise_1.ipynb deleted file mode 100644 index cff2b09..0000000 --- a/beginner/Exercise_1/Exercise_1.ipynb +++ /dev/null @@ -1,493 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "greatest-yugoslavia", - "metadata": {}, - "source": [ - "## Exercise 1\n", - "\n", - "## Objective\n", - "* Create a Git repository from scratch\n", - "* Track changes to files using `git add`, `git status`, and `git commit`\n", - "* Know the state of the Git repository using `git diff` and `git log`\n", - "\n", - "## Structure\n", - "This exercise consists of short descriptions of specific Git commands, followed by a hands-on part where you will be able to execute the corresponding Git commands.\n", - "\n", - "## Helper Functions\n", - "The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with.\n", - "\n", - "For this exercise, we will use the following functions from this file:\n", - " * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work.\n", - " * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely.\n", - "\n", - "\n", - "## Remarks \n", - "_**Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._\n", - "\n", - "_**Note:** The exercises require you to use basic Unix commands. If you are not familiar with Unix systems, we have listed all the necessary commands in the file [Basic Unix Commands](../Unix_Commands.ipynb)._\n", - "\n", - "\n", - "### Initialization\n", - "\n", - "**Start exercises in correct folder:**\n", - "This exercise (and all the exercises that follow) assume that the shell is already in the folder where the exercise notebooks are located. For some reason, the notebook may not switch to the notebook folder by default. In this case, you will need to manually change the directory in order to complete the exercises.\n", - "\n", - "If the `pwd` command returns something like `/home/juckerj/git-course/beginner/Exercise_1`, everything is fine.\n", - "\n", - "If it returns something like `/home/juckerj`, change to the correct directory.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aggressive-newcastle", - "metadata": {}, - "outputs": [], - "source": [ - "# check current directory with \"pwd\"\n", - "\n", - "# in case you are in the wrong directory, navigate to Exercise_1 using \"cd\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "f603d8f2", - "metadata": {}, - "source": [ - "**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "integrated-popularity", - "metadata": {}, - "outputs": [], - "source": [ - "# source the helpers.sh file to be able to use its functions\n", - "source ../helpers.sh\n", - "# init exercise\n", - "init_exercise" - ] - }, - { - "cell_type": "markdown", - "id": "handed-solomon", - "metadata": {}, - "source": [ - "***\n", - "### Optional: clear notebook and restart\n", - "**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "compressed-tooth", - "metadata": {}, - "outputs": [], - "source": [ - "## only execute in case of (serious) trouble ##\n", - "## it will delete your entire beginners_git directory ##\n", - "reset" - ] - }, - { - "cell_type": "markdown", - "id": "extreme-elements", - "metadata": {}, - "source": [ - "***\n", - "## Exercise" - ] - }, - { - "cell_type": "markdown", - "id": "defc889c", - "metadata": {}, - "source": [ - "### Global Git configuration settings\n", - "Before we start using Git, we should set some global configurations. This only needs to be done once, and will be saved for all your future sessions.\n", - "\n", - "First of all, we need to tell Git who we are.\n", - "To do this, run the following lines with your credentials:\n", - "```\n", - "git config --global user.name \"\"\n", - "git config --global user.email \"\"\n", - "```\n", - "**Note:** The email must be identical to the one that is used for your GitHub account." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b35065ff", - "metadata": {}, - "outputs": [], - "source": [ - "# tell Git who you are\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "6852b073", - "metadata": {}, - "source": [ - "At the end of this course, you will learn something about repository managers like GitHub. Recently, they changed their naming policy for the initial branch from *master* to *main*. So we want to tell Git to set our default branch name to *main* as well. \n", - "\n", - "**Note:** See the official Git documentation (https://git-scm.com/docs/git-init#Documentation/git-init.txt--bltbranch-namegt)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "narrow-clarity", - "metadata": {}, - "outputs": [], - "source": [ - "# set 'main' as the default branch name\n", - "git config --global init.defaultBranch main" - ] - }, - { - "cell_type": "markdown", - "id": "b16c9a3c", - "metadata": {}, - "source": [ - "### Create Git repository from scratch\n", - "> Hint: check the [Basic Unix Commands](../Unix_Commands.ipynb) if you don't know how to do the following." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "broad-sword", - "metadata": {}, - "outputs": [], - "source": [ - "# create a new folder (e.g. ) and navigate to it\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6cabbc0b", - "metadata": {}, - "outputs": [], - "source": [ - "# use the command \"git init\" to initiate your first Git repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "affecting-layout", - "metadata": {}, - "source": [ - "You should now get an output similar to:\n", - "```\n", - "Initialized empty Git repository in /beginners_git/git_repo/.git/\n", - "```\n", - "### Make and track changes in files using `git add`, `git commit` and `git status`\n", - "\n", - "In a next step you will add some files to your repository. \n", - "To do this, we will use the *echo* command in combination with the `>` operator to direct its\n", - "output to a file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "further-joining", - "metadata": {}, - "outputs": [], - "source": [ - "# create a text file using the echo-command\n", - "# echo \"\" > first_file.txt\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "authorized-despite", - "metadata": {}, - "outputs": [], - "source": [ - "# use echo and \">\" again to create a second text file\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "expected-humanitarian", - "metadata": {}, - "outputs": [], - "source": [ - "# check the status of your Git repository with \"git status\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "baking-internet", - "metadata": {}, - "source": [ - "You should now get an output similar to:\n", - "\n", - "\n", - "```\n", - "On branch main\n", - "\n", - "No commits yet\n", - "\n", - "Untracked files:\n", - " (use \"git add ...\" to include in what will be committed)\n", - "\tfirst_file.txt\n", - "\tsecond_file.txt\n", - "\n", - "nothing added to commit but untracked files present (use \"git add\" to track)\n", - "```\n", - "\n", - "\n", - "Git has detected the two new files, but the files are not yet included in the Git repository." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "comfortable-polls", - "metadata": {}, - "outputs": [], - "source": [ - "# add the files using \"git add\"\n", - "\n", - "# check your actions with \"git status\" again\n" - ] - }, - { - "cell_type": "markdown", - "id": "developing-reducing", - "metadata": {}, - "source": [ - "Your output should look like this:\n", - "\n", - "```\n", - "On branch main\n", - "\n", - "No commits yet\n", - "\n", - "Changes to be committed:\n", - " (use \"git rm --cached ...\" to unstage)\n", - "\tnew file: first_file.txt\n", - "\tnew file: second_file.txt\n", - "```\n", - "\n", - "The last thing to do is to commit these files. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "written-childhood", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git commit -m \"\"\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "derived-explorer", - "metadata": {}, - "source": [ - "**Congrats!** \n", - "Your files are included in the Git repository.\n", - "\n", - "\n", - "\n", - "### Know state of Git repository using `git diff` and `git log`\n", - "Right now we have two files in our Git repository.\n", - "Let's see what happens when we modify them. We will use the `>>` operator to append a new line of text to our files." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "powered-province", - "metadata": {}, - "outputs": [], - "source": [ - "# append a new line of text with \"echo\" and \">>\" to one of the files\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "current-shelter", - "metadata": {}, - "outputs": [], - "source": [ - "# check state of your repository with \"git status\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "humanitarian-defense", - "metadata": {}, - "source": [ - "Your output should look similar to:\n", - "\n", - "```\n", - "On branch main\n", - "Changes not staged for commit:\n", - " (use \"git add ...\" to update what will be committed)\n", - " (use \"git restore ...\" to discard changes in working directory)\n", - "\tmodified: first_file.txt\n", - "\n", - "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n", - "```\n", - "\n", - "\n", - "When working in a repository, it easily happens that you forget about changes you have made, such as the extra lines you just added. \n", - "Git provides the `git diff` command to check, what new changes are contained in a file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "confidential-soundtrack", - "metadata": {}, - "outputs": [], - "source": [ - "# see local changes of a modified file with \"git diff \"\n" - ] - }, - { - "cell_type": "markdown", - "id": "enabling-shirt", - "metadata": {}, - "source": [ - "In the output\n", - "\n", - "```\n", - "diff --git a/first_file b/first_file\n", - "index 3829ab8..a32d2f3 100644\n", - "--- a/first_file.txt\n", - "+++ b/first_file.txt\n", - "@@ -1 +1,2 @@\n", - " myfirstline\n", - "+mysecondline\n", - "```\n", - "\n", - "We see a lot of information, but all that we care about is the last line: \n", - "The \"+\" indicates that we have a new line in our file.\n", - "\n", - "\n", - "Let's modify the second file as well." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "involved-plaintiff", - "metadata": {}, - "outputs": [], - "source": [ - "# add a new line in the second file as well\n" - ] - }, - { - "cell_type": "markdown", - "id": "featured-indie", - "metadata": {}, - "source": [ - "The next lecture is starting soon, so let's add and commit our changes for safety reasons." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "voluntary-negotiation", - "metadata": {}, - "outputs": [], - "source": [ - "# add the two modified files with \"git add\"\n", - "\n", - "# use \"git status\" to check if your action was successful\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "sublime-council", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git commit -m \"\"\" to commit your files\n" - ] - }, - { - "cell_type": "markdown", - "id": "dedicated-indian", - "metadata": {}, - "source": [ - "**Congrats!** \n", - "But how many commits do you already have in this repository?\n", - "Git does all this tracking for us! \n", - "\n", - "The command `git log` allows us to look back in time and explore what commits are contained in our repository." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "romantic-sharing", - "metadata": {}, - "outputs": [], - "source": [ - "# type \"git log\" to get an overview of the (very short) life of your repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "ignored-local", - "metadata": {}, - "source": [ - "Below you see an example how your log could look like:\n", - "\n", - "```\n", - "commit 26c65dd070e995db55ac46d76cdb5052da03f5cb (HEAD -> main)\n", - "Author: juckerj \n", - "Date: Tue Feb 23 17:16:03 2021 +0100\n", - "\n", - " second commit\n", - "\n", - "commit 495eb9387e4407f3accb57a8f29d7362eead85bb\n", - "Author: juckerj \n", - "Date: Tue Feb 23 16:09:54 2021 +0100\n", - "\n", - " test\n", - "```\n", - "\n", - "We see the unique hash of each commit, its author, and the date of the commit.\n", - "These are all very useful things as we will see later in this course." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/Markdowns/Exercise_1.md b/beginner/Exercise_1_basic_commands.md similarity index 57% rename from beginner/Markdowns/Exercise_1.md rename to beginner/Exercise_1_basic_commands.md index 5645eea..c51bb10 100644 --- a/beginner/Markdowns/Exercise_1.md +++ b/beginner/Exercise_1_basic_commands.md @@ -1,14 +1,17 @@ -## Exercise 1 +# Exercise 1 ## Objective + * Create a Git repository from scratch * Track changes to files using `git add`, `git status`, and `git commit` * Know the state of the Git repository using `git diff` and `git log` ## Structure + This exercise consists of short descriptions of specific Git commands, followed by a hands-on part where you will be able to execute the corresponding Git commands. ## Helper Functions + The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with. For this exercise, we will use the following functions from this file: @@ -17,95 +20,103 @@ For this exercise, we will use the following functions from this file: ## Remarks -_**Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._ -_**Note:** The exercises require you to use basic Unix commands. If you are not familiar with Unix systems, we have listed all the necessary commands in the file [Basic Unix Commands](../Unix_Commands.ipynb)._ +> **Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word. +> **Note:** Some exercises may require the use of basic Unix commands. If you are unfamiliar with Unix systems, refer to the file [Basic Unix Commands](Unix_Commands.md) for a list of all necessary commands. -### Initialization +## Global Git Configuration Settings -**Start exercises in correct folder:** -This exercise (and all the exercises that follow) assume that the shell is already in the folder where the exercise notebooks are located. For some reason, the notebook may not switch to the notebook folder by default. In this case, you will need to manually change the directory in order to complete the exercises. - -If the `pwd` command returns something like `/home/juckerj/git-course/beginner/Exercise_1`, everything is fine. +Before we start using Git, we should set some global configurations. This only needs to be done once, and will be saved for all your future sessions. -If it returns something like `/home/juckerj`, change to the correct directory. +1. First of all, we need to tell Git who we are. +To do this, run the following lines with your credentials: +``` +git config --global user.name "" +git config --global user.email "" +``` +> **Note:** Use your real first and last name as your username and set the same email as your GitHub account. Also, ensure your actual name is set on GitHub; otherwise, your commits will appear under different authors. +At the end of this course, you will learn something about repository managers like GitHub. Recently, they changed their naming policy for the initial branch from *master* to *main*. So we want to tell Git to set our default branch name to *main* as well. +> **Note:** Refer to the official Git documentation (https://git-scm.com/docs/git-init#Documentation/git-init.txt--bltbranch-namegt). +2. Set *main* as the default branch name: ```bash -# check current directory with "pwd" - -# in case you are in the wrong directory, navigate to Exercise_1 using "cd" - +git config --global init.defaultBranch main ``` -**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.** +## Clone the `git-course` Repository + +Now, we are ready to clone the `git-course` repository, which +we need for all exercises in this course. +Open your terminal and navigate to the directory where you want to work on the Git course. Use the following command to verify your current location: ```bash -# source the helpers.sh file to be able to use its functions -source ../helpers.sh -# init exercise -init_exercise +pwd ``` -*** -### Optional: clear notebook and restart -**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.** - +If you would like to work on the Git course in your home directory, you can navigate there using the following command: ```bash -## only execute in case of (serious) trouble ## -## it will delete your entire beginners_git directory ## -reset +cd ~ ``` -*** -## Exercise - -### Global Git configuration settings -Before we start using Git, we should set some global configurations. This only needs to be done once, and will be saved for all your future sessions. +If you are satisfied with your current directory, use the following command to clone the repository containing the course material: -First of all, we need to tell Git who we are. -To do this, run the following lines with your credentials: -``` -git config --global user.name "" -git config --global user.email "" +```bash +git clone git@github.com:C2SM/git-course.git ``` -**Note:** The email must be identical to the one that is used for your GitHub account. +You can now navigate into it with ```bash -# tell Git who you are +cd git-course +``` +## Initialization -``` +Let's switch into the `beginner` folder of our repository: -At the end of this course, you will learn something about repository managers like GitHub. Recently, they changed their naming policy for the initial branch from *master* to *main*. So we want to tell Git to set our default branch name to *main* as well. +```bash +cd beginner +``` -**Note:** See the official Git documentation (https://git-scm.com/docs/git-init#Documentation/git-init.txt--bltbranch-namegt). +--- +> **To initialize the exercise properly, run this code at the very beginning. Check the [Helper Functions](#helper-functions) section above for more explanation.** ```bash -# set 'main' as the default branch name -git config --global init.defaultBranch main +# source the helpers.sh file to be able to use its functions +source helpers.sh +# init exercise +init_exercise ``` -### Create Git repository from scratch -> Hint: check the [Basic Unix Commands](../Unix_Commands.ipynb) if you don't know how to do the following. +Note that the `init_exercise` function will move you out of the `git-course` +repository! You can check this with the `pwd` command. +--- -```bash -# create a new folder (e.g. ) and navigate to it +### Optional: restart exercise repo +⚠️ **In case you messed up somehow, execute the `reset` function. Check the [Helper Functions](#helper-functions) section above for more explanation.** + +```bash +## only execute this in case of (serious) trouble ## +## it will delete your entire beginners_git directory ## +reset ``` +## Exercise -```bash -# use the command "git init" to initiate your first Git repository -``` +### Create a Git repository from scratch +> Hint: check the [Basic Unix Commands](Unix_Commands.md) if you don't know how to do the following. + +1. Create a new folder (e.g. *git_repo*) and navigate to it +2. Use the command `git init` to initiate your first Git repository You should now get an output similar to: ``` @@ -114,27 +125,15 @@ Initialized empty Git repository in /beginners_git/git ### Make and track changes in files using `git add`, `git commit` and `git status` In a next step you will add some files to your repository. -To do this, we will use the *echo* command in combination with the `>` operator to direct its +To do this, we will use the `echo` command in combination with the `>` operator to direct its output to a file. - +1. Create a text file using the `echo` command ```bash -# create a text file using the echo-command -# echo "" > first_file.txt - -``` - - -```bash -# use echo and ">" again to create a second text file - -``` - - -```bash -# check the status of your Git repository with "git status" - +echo "" > first_file.txt ``` +2. Use `echo` and `>` again to create a second text file +3. Check the status of your Git repository with `git status` You should now get an output similar to: @@ -155,14 +154,14 @@ nothing added to commit but untracked files present (use "git add" to track) Git has detected the two new files, but the files are not yet included in the Git repository. - +4. Add the files using `git add` ```bash -# add the files using "git add" - -# check your actions with "git status" again - +git add first_file.txt +git add second_file.txt ``` +5. Check your actions with `git status` again + Your output should look like this: ``` @@ -176,34 +175,21 @@ Changes to be committed: new file: second_file.txt ``` -The last thing to do is to commit these files. - - +6. The last thing to do is to commit these files together with a commit message: ```bash -# use "git commit -m """ - +git commit -m "" ``` **Congrats!** Your files are included in the Git repository. - ### Know state of Git repository using `git diff` and `git log` Right now we have two files in our Git repository. Let's see what happens when we modify them. We will use the `>>` operator to append a new line of text to our files. - -```bash -# append a new line of text with "echo" and ">>" to one of the files - -``` - - -```bash -# check state of your repository with "git status" - -``` +1. Append a new line of text with "echo" and ">>" to one of the files +2. Check state of your repository with `git status` Your output should look similar to: @@ -221,13 +207,9 @@ no changes added to commit (use "git add" and/or "git commit -a") When working in a repository, it easily happens that you forget about changes you have made, such as the extra lines you just added. Git provides the `git diff` command to check, what new changes are contained in a file +3. See local changes of a modified file with `git diff ` -```bash -# see local changes of a modified file with "git diff " - -``` - -In the output +The output should we something like: ``` diff --git a/first_file b/first_file @@ -245,27 +227,15 @@ The "+" indicates that we have a new line in our file. Let's modify the second file as well. - -```bash -# add a new line in the second file as well - -``` +4. Add a new line in the second file The next lecture is starting soon, so let's add and commit our changes for safety reasons. +5. Add the two modified files with `git add` -```bash -# add the two modified files with "git add" - -# use "git status" to check if your action was successful - -``` - - -```bash -# use "git commit -m """ to commit your files +6. Use `git status` to check if your action was successful -``` +7. Now commit your changes with a meaningful commit message **Congrats!** But how many commits do you already have in this repository? @@ -273,27 +243,23 @@ Git does all this tracking for us! The command `git log` allows us to look back in time and explore what commits are contained in our repository. +8. Type `git log` to get an overview of the (very short) life of your repository -```bash -# type "git log" to get an overview of the (very short) life of your repository - -``` - -Below you see an example how your log could look like: +Below you see an example of what your log could look like: ``` commit 26c65dd070e995db55ac46d76cdb5052da03f5cb (HEAD -> main) Author: juckerj Date: Tue Feb 23 17:16:03 2021 +0100 - second commit + add second lines commit 495eb9387e4407f3accb57a8f29d7362eead85bb Author: juckerj Date: Tue Feb 23 16:09:54 2021 +0100 - test + create two files ``` We see the unique hash of each commit, its author, and the date of the commit. -These are all very useful things as we will see later in this course. +These are all very useful things as we will see later in this course. \ No newline at end of file diff --git a/beginner/Exercise_2/Exercise_2.ipynb b/beginner/Exercise_2/Exercise_2.ipynb deleted file mode 100644 index bd8a032..0000000 --- a/beginner/Exercise_2/Exercise_2.ipynb +++ /dev/null @@ -1,383 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "crude-martial", - "metadata": {}, - "source": [ - "## Exercise 2\n", - "\n", - "## Objective\n", - " * Learn how to work with branches and switch between them using `git switch`.\n", - " * Note: `git checkout` can be used as an alternative to `git switch`. However, it has different features that have caused confusion among users in the past. So we won't use it here, but show the alternative commands in brackets, as some older Git versions don't have this option yet.\n", - "\n", - "## Structure\n", - "In this exercise, we will work on scheduling a two-day conference using two files that contain the schedules for day 1 and day 2 (*schedule_day1.txt* and *schedule_day2.txt*). To add events to the schedules (e.g., talks, poster sessions, etc.), we will work on separate branches so as not to mix things up.\n", - "Again, this exercise will consist of short descriptions of specific Git commands, followed by a hands-on part where you will be able to execute the corresponding Git commands.\n", - "\n", - "## Helper Functions\n", - "The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with.\n", - "\n", - "For this exercise, we will use the following functions from this file:\n", - " * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work.\n", - " * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely.\n", - " * `init_simple_repo`: This will set up a Git repository containing a first version of *schedule_day1.txt* and *schedule_day2.txt* on the *main* branch.\n", - "\n", - "## Remarks\n", - "_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._\n", - "\n", - "_**Note:** Always run `git commit` and `git merge` with a Git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._\n", - "\n", - "### Initialization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "formal-wound", - "metadata": {}, - "outputs": [], - "source": [ - "# check current directory with \"pwd\"\n", - "\n", - "# in case you are in the wrong directory, navigate to Exercise_2 using \"cd\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "399abef5", - "metadata": {}, - "source": [ - "**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "logical-malawi", - "metadata": {}, - "outputs": [], - "source": [ - "# source the helpers.sh file to be able to use its functions\n", - "source ../helpers.sh\n", - "# init exercise\n", - "init_exercise" - ] - }, - { - "cell_type": "markdown", - "id": "continent-court", - "metadata": {}, - "source": [ - "***\n", - "### Optional: clear notebook and restart\n", - "**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "accessible-municipality", - "metadata": {}, - "outputs": [], - "source": [ - "## only execute in case of (serious) trouble ##\n", - "## it will delete your entire beginners_git directory ##\n", - "reset" - ] - }, - { - "cell_type": "markdown", - "id": "rotary-smile", - "metadata": {}, - "source": [ - "***\n", - "## Exercise\n", - "\n", - "### Learn how to work with branches and switch between them using `git switch`\n", - "\n", - "First, we will set up a simple Git repository for you using one of the helper functions:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1fab8b64", - "metadata": {}, - "outputs": [], - "source": [ - "# this line will set up a simple Git repository for you\n", - "init_simple_repo" - ] - }, - { - "cell_type": "markdown", - "id": "b5f6b0dd", - "metadata": {}, - "source": [ - "In the output above we see two files:\n", - " * *schedule_day1.txt*\n", - " * *schedule_day2.txt*\n", - " \n", - "Let's have a look at them using the `cat` command:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "embedded-looking", - "metadata": {}, - "outputs": [], - "source": [ - "# display content with cat: \"cat \"\n" - ] - }, - { - "cell_type": "markdown", - "id": "manual-morning", - "metadata": {}, - "source": [ - "As you can see, there is still a lot of free time available to add talks, poster sessions, breaks, etc.\n", - "\n", - "To keep things organized, we will do this in two different Git branches, one for scheduling day 1 and one for scheduling day 2.\n", - "\n", - "**Let's get started!**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "lesbian-military", - "metadata": {}, - "outputs": [], - "source": [ - "# create a new branch for planning day 1\n", - "# use \"git switch -c \" to create a new branch\n", - "# (Alternative: \"git checkout -b \")\n" - ] - }, - { - "cell_type": "markdown", - "id": "appreciated-elements", - "metadata": {}, - "source": [ - "From now on, we will make all modifications to the schedules directly in Jupyter Notebooks.\n", - " * On the start page, go to the folder *beginners_git* (outside of *git-course*)\n", - " * Navigate to the folder *conference_planning*\n", - " * Open *schedule_day1.txt*\n", - " * Add more information to the schedule, such as planned talks, poster sessions, lunch, etc.\n", - " \n", - "**Remember to save your changes before you come back!**\n", - "\n", - "After saving, we run `git status` to see if Git has tracked our changes." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "powered-selling", - "metadata": {}, - "outputs": [], - "source": [ - "# see if Git tracked our changes\n" - ] - }, - { - "cell_type": "markdown", - "id": "decent-polls", - "metadata": {}, - "source": [ - "The output should look like:\n", - "```\n", - "On branch planning_day1\n", - "Changes not staged for commit:\n", - " (use \"git add ...\" to update what will be committed)\n", - " (use \"git restore ...\" to discard changes in working directory)\n", - "\tmodified: schedule_day1.txt\n", - "\n", - "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n", - "```\n", - "\n", - "Now do a commit with those changes." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "recent-cookbook", - "metadata": {}, - "outputs": [], - "source": [ - "# add schedule_day1.txt and commit it (don't forget the commit message)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "stylish-contemporary", - "metadata": {}, - "source": [ - "For the planning of the other day, we want to use another Git branch.\n", - "To keep track of all the different branches, Git provides the `git branch` command to see all branches of a repository.\n", - "The * indicates our current branch." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "colonial-language", - "metadata": {}, - "outputs": [], - "source": [ - "# see all branches of our Git repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "stunning-illinois", - "metadata": {}, - "source": [ - "We can easily switch between these branches using the `git switch` command.\n", - "Don't worry -> Git will keep all your work done on that branch." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "therapeutic-permit", - "metadata": {}, - "outputs": [], - "source": [ - "# go back to branch main using \"git switch main\"\n", - "# (Alternative: \"git checkout main\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "adjacent-angle", - "metadata": {}, - "source": [ - "Create a new branch for scheduling day 2 and extend the *schedule_day2.txt* file in that branch, similar to what was done for the *schedule_day1.txt* file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "optional-wisdom", - "metadata": {}, - "outputs": [], - "source": [ - "# create a new branch for the planning of day 2\n" - ] - }, - { - "cell_type": "markdown", - "id": "ef2225b1", - "metadata": {}, - "source": [ - "Now open *schedule_day2.txt*, make changes, and save them. Proceed to commit your changes." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "conscious-rugby", - "metadata": {}, - "outputs": [], - "source": [ - "# add and commit your changes\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "proud-smell", - "metadata": {}, - "outputs": [], - "source": [ - "# view all branches of your Git repository again\n" - ] - }, - { - "cell_type": "markdown", - "id": "afraid-norman", - "metadata": {}, - "source": [ - "The output should look like this:\n", - "\n", - "```\n", - " main\n", - " planning_day1\n", - "* planning_day2\n", - "```\n", - "\n", - "Our Git repository now contains:\n", - " * Branch *meaningful_branch_name_A* with modifications to *schedule_day1.txt*\n", - " * Branch *meaningful_branch_name_B* with modifications to *schedule_day2.txt*\n", - " * Branch *main* with the original version of *schedule_day1.txt* and *schedule_day2.txt*\n", - " \n", - "Using `git switch` it is easy to jump between these branches and modify our schedules further.\n", - "To show its capabilities, we will quickly switch between the branches and see how our schedules change." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "applicable-vocabulary", - "metadata": {}, - "outputs": [], - "source": [ - "# display the content of schedule_day1.txt and schedule_day2.txt using \"cat\"\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "oriented-attempt", - "metadata": {}, - "outputs": [], - "source": [ - "# switch to the \"main\" branch and do the same again\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "statutory-green", - "metadata": {}, - "outputs": [], - "source": [ - "# switch to the branch for scheduling day 1 and do the same\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "88eccb78", - "metadata": {}, - "source": [ - "You should see that the output for the two files is slightly different depending on which branch you are on." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/Markdowns/Exercise_2.md b/beginner/Exercise_2_switch_branches.md similarity index 54% rename from beginner/Markdowns/Exercise_2.md rename to beginner/Exercise_2_switch_branches.md index 4a92b28..ba8c9e9 100644 --- a/beginner/Markdowns/Exercise_2.md +++ b/beginner/Exercise_2_switch_branches.md @@ -1,14 +1,17 @@ -## Exercise 2 +# Exercise 2 ## Objective + * Learn how to work with branches and switch between them using `git switch`. * Note: `git checkout` can be used as an alternative to `git switch`. However, it has different features that have caused confusion among users in the past. So we won't use it here, but show the alternative commands in brackets, as some older Git versions don't have this option yet. ## Structure + In this exercise, we will work on scheduling a two-day conference using two files that contain the schedules for day 1 and day 2 (*schedule_day1.txt* and *schedule_day2.txt*). To add events to the schedules (e.g., talks, poster sessions, etc.), we will work on separate branches so as not to mix things up. Again, this exercise will consist of short descriptions of specific Git commands, followed by a hands-on part where you will be able to execute the corresponding Git commands. ## Helper Functions + The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with. For this exercise, we will use the following functions from this file: @@ -16,65 +19,34 @@ For this exercise, we will use the following functions from this file: * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely. * `init_simple_repo`: This will set up a Git repository containing a first version of *schedule_day1.txt* and *schedule_day2.txt* on the *main* branch. -## Remarks -_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._ - -_**Note:** Always run `git commit` and `git merge` with a Git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._ - -### Initialization - - -```bash -# check current directory with "pwd" - -# in case you are in the wrong directory, navigate to Exercise_2 using "cd" - -``` - -**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.** +## Remarks +> **Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word. -```bash -# source the helpers.sh file to be able to use its functions -source ../helpers.sh -# init exercise -init_exercise -``` +> **Note:** Some exercises may require the use of basic Unix commands. If you are unfamiliar with Unix systems, refer to the file [Basic Unix Commands](Unix_Commands.md) for a list of all necessary commands. -*** -### Optional: clear notebook and restart -**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.** - - -```bash -## only execute in case of (serious) trouble ## -## it will delete your entire beginners_git directory ## -reset -``` +If everything is still set up from the last exercise, you can continue with [this exercise](#exercise) directly. +Otherwise, please refer to the [Initialization from Exercise 1](Exercise_1_basic_commands.md#initialization). -*** ## Exercise ### Learn how to work with branches and switch between them using `git switch` -First, we will set up a simple Git repository for you using one of the helper functions: - +1. First, we will set up a simple Git repository for you using one of the helper functions. +The following command will set up a simple Git repository called *conference_planning* in the *beginners_git* directory for you and navigate you to it: ```bash -# this line will set up a simple Git repository for you init_simple_repo ``` In the output above we see two files: * *schedule_day1.txt* * *schedule_day2.txt* - -Let's have a look at them using the `cat` command: +2. Let's have a look at them using the `cat` command: ```bash -# display content with cat: "cat " - +cat schedule_day1.txt ``` As you can see, there is still a lot of free time available to add talks, poster sessions, breaks, etc. @@ -82,30 +54,15 @@ As you can see, there is still a lot of free time available to add talks, poster To keep things organized, we will do this in two different Git branches, one for scheduling day 1 and one for scheduling day 2. **Let's get started!** - - +1. Create a new branch for planning day 1: ```bash -# create a new branch for planning day 1 -# use "git switch -c " to create a new branch -# (Alternative: "git checkout -b ") - +git switch -c +# (Alternative: "git checkout -b ") ``` -From now on, we will make all modifications to the schedules directly in Jupyter Notebooks. - * On the start page, go to the folder *beginners_git* (outside of *git-course*) - * Navigate to the folder *conference_planning* - * Open *schedule_day1.txt* - * Add more information to the schedule, such as planned talks, poster sessions, lunch, etc. - -**Remember to save your changes before you come back!** - -After saving, we run `git status` to see if Git has tracked our changes. - - -```bash -# see if Git tracked our changes +2. Open *schedule_day1.txt* (you should find it in */beginners_git/conference_planning*) and add more information to the schedule, such as planned talks, poster sessions, lunch, etc. -``` +3. After saving, we run `git status` to see if Git has tracked our changes. The output should look like: ``` @@ -118,57 +75,30 @@ Changes not staged for commit: no changes added to commit (use "git add" and/or "git commit -a") ``` -Now do a commit with those changes. - - -```bash -# add schedule_day1.txt and commit it (don't forget the commit message) - - -``` +4. Add your changes to the staging area and commit them. For the planning of the other day, we want to use another Git branch. To keep track of all the different branches, Git provides the `git branch` command to see all branches of a repository. -The * indicates our current branch. - +The * indicates our current branch. Hit the `q` key to exit the branch view. ```bash -# see all branches of our Git repository - +git branch ``` We can easily switch between these branches using the `git switch` command. Don't worry -> Git will keep all your work done on that branch. - +5. Switch back to *main* branch: ```bash -# go back to branch main using "git switch main" +git switch main # (Alternative: "git checkout main") - -``` - -Create a new branch for scheduling day 2 and extend the *schedule_day2.txt* file in that branch, similar to what was done for the *schedule_day1.txt* file. - - -```bash -# create a new branch for the planning of day 2 - -``` - -Now open *schedule_day2.txt*, make changes, and save them. Proceed to commit your changes. - - -```bash -# add and commit your changes - - ``` +6. Create a new branch for scheduling day 2 and extend the *schedule_day2.txt* file in that branch, similar to what was done for the *schedule_day1.txt* file. -```bash -# view all branches of your Git repository again +7. Add and commit the changes of *schedule_day2.txt* in your new branch. -``` +8. View all branches of your Git repository again The output should look like this: @@ -186,27 +116,8 @@ Our Git repository now contains: Using `git switch` it is easy to jump between these branches and modify our schedules further. To show its capabilities, we will quickly switch between the branches and see how our schedules change. +9. Display the content of *schedule_day1.txt* and *schedule_day2.txt* using `cat`. -```bash -# display the content of schedule_day1.txt and schedule_day2.txt using "cat" - - -``` - - -```bash -# switch to the "main" branch and do the same again - - - -``` - - -```bash -# switch to the branch for scheduling day 1 and do the same - - - -``` +10. Repeat displaying the content of the files after switching to the *main* branch and the branch for scheduling day 1. You should see that the output for the two files is slightly different depending on which branch you are on. diff --git a/beginner/Exercise_3/Exercise_3.ipynb b/beginner/Exercise_3/Exercise_3.ipynb deleted file mode 100644 index a9f39e9..0000000 --- a/beginner/Exercise_3/Exercise_3.ipynb +++ /dev/null @@ -1,550 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "frequent-pension", - "metadata": {}, - "source": [ - "## Exercise 3\n", - "\n", - "## Objective\n", - " * Restore the version of files at some point in the Git history\n", - " * Merge two branches (without merge conflicts)\n", - " * Delete unused branches\n", - " \n", - "## Structure\n", - "In this exercise, we will continue working on the schedule for the two-day conference using *schedule_day1.txt* and *schedule_day2.txt* for each day's schedule. First, we need to revert the schedules back to a specific commit. Then we modify the same file, but on different branches. Finally, we merge all our changes back to the *main* branch.\n", - "\n", - "Again, this exercise will consist of short descriptions of specific Git commands, followed by a hands-on part where you will be able to execute the corresponding Git commands.\n", - "\n", - "## Helper Functions\n", - "The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with.\n", - "\n", - "For this exercise, we will use the following functions from this file:\n", - " * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work.\n", - " * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely.\n", - " * `init_repo`: This sets up a Git repository as in Exercise 2, but with more commits.\n", - "\n", - "## Remarks\n", - "_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._\n", - "\n", - "_**Reminder:** Always run `git commit` and `git merge` with a git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._\n", - "\n", - "### Initialization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "magnetic-price", - "metadata": {}, - "outputs": [], - "source": [ - "# check current directory with \"pwd\"\n", - "\n", - "# in case you are in the wrong directory, navigate to Exercise_3 using \"cd\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "37a897d2", - "metadata": {}, - "source": [ - "**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cleared-wellington", - "metadata": {}, - "outputs": [], - "source": [ - "# source the helpers.sh file to be able to use its functions\n", - "source ../helpers.sh\n", - "# init exercise\n", - "init_exercise" - ] - }, - { - "cell_type": "markdown", - "id": "listed-shell", - "metadata": {}, - "source": [ - "***\n", - "### Optional: clear notebook and restart\n", - "**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "genuine-companion", - "metadata": {}, - "outputs": [], - "source": [ - "## only execute in case of (serious) trouble ##\n", - "## it will delete your entire beginners_git directory ##\n", - "reset" - ] - }, - { - "cell_type": "markdown", - "id": "average-while", - "metadata": {}, - "source": [ - "***\n", - "## Exercise\n", - "\n", - "### Restore versions of files at any point in the Git history\n", - "\n", - "First, we will set up a simple Git repository for you using one of the helper functions:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "oriented-labor", - "metadata": {}, - "outputs": [], - "source": [ - "# this line will setup a simple Git repository for you\n", - "init_repo" - ] - }, - { - "cell_type": "markdown", - "id": "german-tenant", - "metadata": {}, - "source": [ - "Review the schedules for the two days by opening the files as before:\n", - "\n", - " * On the start page, go to the folder *beginners_git* (outside of *git-course*)\n", - " * Navigate to the folder *conference_planning*\n", - " * Open *schedule_day1.txt* and *schedule_day2.txt*\n", - "\n", - "The schedules for both days start with talks.\n", - "\n", - "Originally we planned poster sessions in the morning, but the invited professors only had time in the morning to give their talks, so we changed the poster sessions to talks (see history).\n", - "\n", - "However, the professors have now canceled their talks and we want to have the poster sessions in the morning again.\n", - "\n", - "To avoid doing the same work twice, we want to reuse the old schedules that we designed in the first place.\n", - "\n", - "We can use `git restore` to get any version of a file along its Git history.\n", - "\n", - "Just run `git restore -s `.\n", - "\n", - "**Note**: \n", - "For simplicity, we've used the `-s` option in the `git restore` command. Note that `-s` is a shorthand for `--source`, which you can also use interchangeably. The primary difference lies in the syntax: use `-s ` for a shorter command, or `--source=` if you prefer a more explicit approach. Both options perform the same function: specifying the source from which to restore. Whether you prefer `-s` for brevity or `--source` for clarity is up to you.\n", - "\n", - "\n", - "\n", - "Let's try it out for *schedule_day1.txt* first!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "photographic-reliance", - "metadata": {}, - "outputs": [], - "source": [ - "# restore the version of schedule_day1.txt before commit: \"Change poster sessions to talks\"\n", - "# \"git restore -s \"\n", - "# (Alternative - includes \"git add\": \"git checkout \")\n" - ] - }, - { - "cell_type": "markdown", - "id": "realistic-worship", - "metadata": {}, - "source": [ - "Refresh the jupyter notebook page with *schedule_day1.txt* and take a look at it.\n", - "You will see that we now have a poster session in the morning again.\n", - "\n", - "Do the same for *schedule_day2.txt*." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "political-ontario", - "metadata": {}, - "outputs": [], - "source": [ - "# restore schedule_day2.txt before commit \"Change poster sessions to talks\"\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "changing-romance", - "metadata": {}, - "outputs": [], - "source": [ - "# check if Git tracked our changes\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2d7c4743", - "metadata": {}, - "outputs": [], - "source": [ - "# add and commit your updated schedules\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "romantic-million", - "metadata": {}, - "outputs": [], - "source": [ - "# \"git log\" to see the Git history\n" - ] - }, - { - "cell_type": "markdown", - "id": "congressional-hands", - "metadata": {}, - "source": [ - "Each *commit hash* is unique, so you can always go to any version of the tracked files, *even* across different branches.\n", - "\n", - "Suddenly we decide to not have the workshop on day 1 anymore. So we restore *schedule_day1.txt* before the \"Add workshops\" commit." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "micro-uncle", - "metadata": {}, - "outputs": [], - "source": [ - "# restore schedule_day1.txt at right commit\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "324173f2", - "metadata": {}, - "outputs": [], - "source": [ - "# add and commit schedule_day1.txt\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "distributed-corporation", - "metadata": {}, - "outputs": [], - "source": [ - "# execute \"git log --oneline\" for short summary\n" - ] - }, - { - "cell_type": "markdown", - "id": "great-latest", - "metadata": {}, - "source": [ - "Your output should look similar to:\n", - "```\n", - "b7bd111 (HEAD -> main) Remove workshop on day1\n", - "f6c3f04 Change talks back to poster sessions\n", - "5889296 Change poster sessions to talks\n", - "464fc92 Add workshop\n", - "e53b1e0 Add coffee break\n", - "f1b23c1 Add poster sessions in the morning\n", - "f636890 Add schedule_day2\n", - "206f724 Add schedule_day1\n", - "1c1e740 Changed poster sessions to talks\n", - "154f0dc Add coffee break\n", - "a98abe7 Add poster sessions in the morning\n", - "ca117ca Add schedule_day2\n", - "b82e094 Add schedule_day1\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "id": "infrared-catalog", - "metadata": {}, - "source": [ - "### Merge two branches (without merge conflicts)\n", - "In this part of the exercise, we will continue working on *schedule_day1.txt*.\n", - "There are two sections in *schedule_day1.txt*, which we will change on separate branches:\n", - " * *daily_program*\n", - " * *evening_activity*\n", - " \n", - "Note: Try to avoid merge conflicts by not changing the same part of a file in two branches you want to merge (usually the *main* branch and a branch you want to merge into the *main* branch). There are, of course, ways to deal with merge conflicts, and we will learn how to deal with them later in this course, but for now we will try to avoid them. If you follow the descriptions below, you should not run into a merge conflict." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "smooth-bunch", - "metadata": {}, - "outputs": [], - "source": [ - "# switch to a new branch for the evening activity\n" - ] - }, - { - "cell_type": "markdown", - "id": "polish-print", - "metadata": {}, - "source": [ - "Open the schedules as described before and add evening activities and don't forget to save your changes. Come back here and commit the changes." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "infinite-retirement", - "metadata": {}, - "outputs": [], - "source": [ - "# add and commit your changes\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "adjusted-specification", - "metadata": {}, - "outputs": [], - "source": [ - "# go back to the main branch using \"git switch\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "6d478dbb", - "metadata": {}, - "source": [ - "Now create another branch to add more to the daily program. Add at least one more event to the daily program." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "unlikely-carter", - "metadata": {}, - "outputs": [], - "source": [ - "# switch to a new branch and add more events to the daily program\n" - ] - }, - { - "cell_type": "markdown", - "id": "applicable-alberta", - "metadata": {}, - "source": [ - "Make changes in the files and save them." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "responsible-revolution", - "metadata": {}, - "outputs": [], - "source": [ - "# add and commit your changes\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cutting-obligation", - "metadata": {}, - "outputs": [], - "source": [ - "# switch back to branch main and run \"git branch\"\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "toxic-toolbox", - "metadata": {}, - "source": [ - "`git branch` should output something like this:\n", - "```\n", - " evening_activity\n", - "* main\n", - " daily_program\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "integral-transition", - "metadata": {}, - "source": [ - "Let's put the pieces of the schedules together. For that we use the `git merge` functionality. \n", - "It allows us to merge files with different text from different branches.\n", - "\n", - "\n", - "To merge all modifications from a branch into the current branch, we type `git merge `" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aboriginal-foundation", - "metadata": {}, - "outputs": [], - "source": [ - "# merge evening activity into main (make sure you are on the main branch for that)\n" - ] - }, - { - "cell_type": "markdown", - "id": "handy-disaster", - "metadata": {}, - "source": [ - "Git just performed a so-called **fast-forward merge**. This means that there is a linear path\n", - "between the two merged branches. See the slides for more detailed information about it. \n", - "\n", - "**Most important:** \n", - "Git does **NOT** create an additional commit to perform the merge. It only appends the commit from the branch *evening_activity* to the HEAD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "natural-affiliation", - "metadata": {}, - "outputs": [], - "source": [ - "# git log to see the added commit\n" - ] - }, - { - "cell_type": "markdown", - "id": "blocked-burke", - "metadata": {}, - "source": [ - "Check the contents of the schedules.\n", - "\n", - "As you can see, we successfully merged our changes from the *evening_activity* branch into the *main* branch.\n", - "\n", - "Let's do the same, but for the changes in the branch for the daily program." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "light-property", - "metadata": {}, - "outputs": [], - "source": [ - "# merge daily_program into main \n", - "# Important: add a merge message (-m \"Merge daily_program\") or your jupyter notebook may crash\n" - ] - }, - { - "cell_type": "markdown", - "id": "whole-brand", - "metadata": {}, - "source": [ - "For this merge, Git performs what is called a **3-way merge**, because the path between the two branches is no longer linear due to the merge of the branch for planning the evening activities. So Git creates a **merge commit** to merge the two histories together. Take a look at the schedules and see what they look like. Then check out the new history of your current branch." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "metric-rates", - "metadata": {}, - "outputs": [], - "source": [ - "# git log --oneline to see the history\n" - ] - }, - { - "cell_type": "markdown", - "id": "promising-morning", - "metadata": {}, - "source": [ - "Your Git log looks like the following:\n", - "```\n", - "c0d0459 (HEAD -> main) Merge daily_program\n", - "b1be3b4 (daily_program) Add talk\n", - "4d93eac (evening_activity) Add evening activity\n", - "dd09add No more workshop\n", - "cc345c6 Revert poster sessions\n", - "ebc8d06 Change poster sessions to talks\n", - "56c65e8 Add workshops\n", - "e0ced97 Add coffee break\n", - "90b9b5e Add poster sessions in the morning\n", - "2a00ec0 Add schedule_day2\n", - "20be4d2 Add schedule_day1\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "motivated-entertainment", - "metadata": {}, - "source": [ - "### Delete unused branches\n", - "\n", - "After merging, it is good practice to delete merged branches. \n", - "\n", - "The command `git branch -d ` can do this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "figured-worcester", - "metadata": {}, - "outputs": [], - "source": [ - "# delete the evening_activity branch\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "subject-logic", - "metadata": {}, - "outputs": [], - "source": [ - "# delete the daily_program branch\n" - ] - }, - { - "cell_type": "markdown", - "id": "grateful-niagara", - "metadata": {}, - "source": [ - "**Congrats, your Git skills are getting better and better!**" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/Markdowns/Exercise_3.md b/beginner/Exercise_3_restore_merge.md similarity index 56% rename from beginner/Markdowns/Exercise_3.md rename to beginner/Exercise_3_restore_merge.md index b32b92d..1cc3f83 100644 --- a/beginner/Markdowns/Exercise_3.md +++ b/beginner/Exercise_3_restore_merge.md @@ -1,4 +1,4 @@ -## Exercise 3 +# Exercise 3 ## Objective * Restore the version of files at some point in the Git history @@ -18,66 +18,34 @@ For this exercise, we will use the following functions from this file: * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely. * `init_repo`: This sets up a Git repository as in Exercise 2, but with more commits. -## Remarks -_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._ +## Remarks -_**Reminder:** Always run `git commit` and `git merge` with a git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._ +> **Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word. -### Initialization +> **Note:** Some exercises may require the use of basic Unix commands. If you are unfamiliar with Unix systems, refer to the file [Basic Unix Commands](Unix_Commands.md) for a list of all necessary commands. +If everything is still set up from the last exercise, you can continue with [this exercise](#exercise) directly. +Otherwise, please refer to the [Initialization from Exercise 1](Exercise_1_basic_commands.md#initialization). -```bash -# check current directory with "pwd" - -# in case you are in the wrong directory, navigate to Exercise_3 using "cd" - -``` - -**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.** - - -```bash -# source the helpers.sh file to be able to use its functions -source ../helpers.sh -# init exercise -init_exercise -``` - -*** -### Optional: clear notebook and restart -**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.** - - -```bash -## only execute in case of (serious) trouble ## -## it will delete your entire beginners_git directory ## -reset -``` - -*** ## Exercise ### Restore versions of files at any point in the Git history First, we will set up a simple Git repository for you using one of the helper functions: - ```bash -# this line will setup a simple Git repository for you init_repo ``` -Review the schedules for the two days by opening the files as before: - - * On the start page, go to the folder *beginners_git* (outside of *git-course*) - * Navigate to the folder *conference_planning* - * Open *schedule_day1.txt* and *schedule_day2.txt* +1. Review the schedules for the two days in the files *schedule_day1.txt* and *schedule_day2.txt*. The schedules for both days start with talks. -Originally we planned poster sessions in the morning, but the invited professors only had time in the morning to give their talks, so we changed the poster sessions to talks (see history). +Originally we planned poster sessions in the morning, but the invited professors only had time in the morning to give their talks, so we changed the poster sessions to talks. -However, the professors have now canceled their talks and we want to have the poster sessions in the morning again. +2. Check the Git history for the commit that changed the poster sessions to talks. + +The professors have now canceled their talks and we want to have the poster sessions in the morning again. To avoid doing the same work twice, we want to reuse the old schedules that we designed in the first place. @@ -88,70 +56,25 @@ Just run `git restore -s `. **Note**: For simplicity, we've used the `-s` option in the `git restore` command. Note that `-s` is a shorthand for `--source`, which you can also use interchangeably. The primary difference lies in the syntax: use `-s ` for a shorter command, or `--source=` if you prefer a more explicit approach. Both options perform the same function: specifying the source from which to restore. Whether you prefer `-s` for brevity or `--source` for clarity is up to you. +2. Undo "Change poster sessions to talks" by restoring the *schedule_day1.txt* to the commit before the change. +3. Review *schedule_day1.txt* to see if the talk has been changed back to a poster session. -Let's try it out for *schedule_day1.txt* first! - - -```bash -# restore the version of schedule_day1.txt before commit: "Change poster sessions to talks" -# "git restore -s " -# (Alternative - includes "git add": "git checkout ") - -``` - -Refresh the jupyter notebook page with *schedule_day1.txt* and take a look at it. -You will see that we now have a poster session in the morning again. - -Do the same for *schedule_day2.txt*. - - -```bash -# restore schedule_day2.txt before commit "Change poster sessions to talks" - -``` - - -```bash -# check if Git tracked our changes - -``` +4. Do exactly the same for *schedule_day2.txt*. +5. Check if Git tracked the changes. -```bash -# add and commit your updated schedules +6. Add and commit your updated schedules - -``` - - -```bash -# "git log" to see the Git history - -``` +7. Now check the Git history Each *commit hash* is unique, so you can always go to any version of the tracked files, *even* across different branches. -Suddenly we decide to not have the workshop on day 1 anymore. So we restore *schedule_day1.txt* before the "Add workshops" commit. +8. You decide to not have the workshop on day 1 anymore. So restore *schedule_day1.txt* before the "Add workshops" commit. +9. Add and commit *schedule_day1.txt*. -```bash -# restore schedule_day1.txt at right commit - -``` - - -```bash -# add and commit schedule_day1.txt - - -``` - - -```bash -# execute "git log --oneline" for short summary - -``` +10. Check the Git history with `git log --oneline` for a short summary. Your output should look similar to: ``` @@ -179,52 +102,21 @@ There are two sections in *schedule_day1.txt*, which we will change on separate Note: Try to avoid merge conflicts by not changing the same part of a file in two branches you want to merge (usually the *main* branch and a branch you want to merge into the *main* branch). There are, of course, ways to deal with merge conflicts, and we will learn how to deal with them later in this course, but for now we will try to avoid them. If you follow the descriptions below, you should not run into a merge conflict. +1. Switch to a new branch for the evening activity. -```bash -# switch to a new branch for the evening activity +2. Open the schedules add evening activities. -``` - -Open the schedules as described before and add evening activities and don't forget to save your changes. Come back here and commit the changes. - - -```bash -# add and commit your changes +3. Add and commit the changes. +4. Go back to the *main* branch using `git switch` (if you don't go back to the *main* branch but create a new branch, it will be based on the current branch and not the *main* branch). -``` +5. Now create another branch to add more to the daily program. Add at least one more event to the daily program. +6. Add and commit your changes -```bash -# go back to the main branch using "git switch" +7. Now switch back to branch *main* and run `git branch` -``` - -Now create another branch to add more to the daily program. Add at least one more event to the daily program. - - -```bash -# switch to a new branch and add more events to the daily program - -``` - -Make changes in the files and save them. - - -```bash -# add and commit your changes - - -``` - - -```bash -# switch back to branch main and run "git branch" - - -``` - -`git branch` should output something like this: +The output should look like: ``` evening_activity * main @@ -237,11 +129,7 @@ It allows us to merge files with different text from different branches. To merge all modifications from a branch into the current branch, we type `git merge ` - -```bash -# merge evening activity into main (make sure you are on the main branch for that) - -``` +8. Merge evening activity into the *main* branch (make sure you are on the main branch for that). Git just performed a so-called **fast-forward merge**. This means that there is a linear path between the two merged branches. See the slides for more detailed information about it. @@ -249,32 +137,21 @@ between the two merged branches. See the slides for more detailed information ab **Most important:** Git does **NOT** create an additional commit to perform the merge. It only appends the commit from the branch *evening_activity* to the HEAD. - -```bash -# git log to see the added commit - -``` +9. Check Git history to see the added commit. Check the contents of the schedules. -As you can see, we successfully merged our changes from the *evening_activity* branch into the *main* branch. +As you can see, we successfully merged our changes from the *evening_activity* branch into the *main* branch. After merging a branch, it is always good practice to delete it. -Let's do the same, but for the changes in the branch for the daily program. - - -```bash -# merge daily_program into main -# Important: add a merge message (-m "Merge daily_program") or your jupyter notebook may crash +10. Delete the branch for the evening activities with `git branch -d `. -``` - -For this merge, Git performs what is called a **3-way merge**, because the path between the two branches is no longer linear due to the merge of the branch for planning the evening activities. So Git creates a **merge commit** to merge the two histories together. Take a look at the schedules and see what they look like. Then check out the new history of your current branch. +Let's do the same, but for the changes in the branch for the daily program. +11. Merge the branch for the daily program into the *main* branch. -```bash -# git log --oneline to see the history +For this merge, Git performs what is called a **3-way merge**, because the path between the two branches is no longer linear due to the merge of the branch for planning the evening activities. So Git creates a **merge commit** to merge the two histories together. -``` +12. Take a look at the schedules and see what they look like. Then check out the new history of your current branch. Your Git log looks like the following: ``` @@ -291,22 +168,6 @@ e0ced97 Add coffee break 20be4d2 Add schedule_day1 ``` -### Delete unused branches - -After merging, it is good practice to delete merged branches. - -The command `git branch -d ` can do this. - - -```bash -# delete the evening_activity branch - -``` - - -```bash -# delete the daily_program branch - -``` +13. Again, make sure to delete the branch you just merged. **Congrats, your Git skills are getting better and better!** diff --git a/beginner/Exercise_4/Exercise_4.ipynb b/beginner/Exercise_4/Exercise_4.ipynb deleted file mode 100644 index 8652002..0000000 --- a/beginner/Exercise_4/Exercise_4.ipynb +++ /dev/null @@ -1,578 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "executed-paris", - "metadata": {}, - "source": [ - "## Exercise 4\n", - "\n", - "## Objective\n", - " * Practice the typical Git workflow\n", - " * Understand the function of a *.gitignore* file, and learn the steps involved in creating and configuring it within a Git repository.\n", - " \n", - "## Structure\n", - "\n", - "In this exercise, we won't be learning any new Git commands. Rather, we will review all the commands and workflows we learned in the previous exercises. We will do this by working on the *conference_schedule.txt* document and simulating a possible workflow. Since this is a review, there will be less explanation for that part of this exercise.\n", - "\n", - "In addition to that, we will explore a crucial aspect of Git: the *.gitignore* file. We'll learn how to create and configure this file to manage the files that Git should ignore, enhancing our typical workflow.\n", - "\n", - "\n", - "\n", - "## Helper Functions\n", - "The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with.\n", - "\n", - "For this exercise, we will use the following functions from this file:\n", - " * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work.\n", - " * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely.\n", - " * `init_repo_empty_schedule`: This will create the directory *conference_planning* and a file *conference_schedule.txt* with an empty schedule.\n", - "\n", - "## Remarks\n", - "_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._\n", - "\n", - "_**Reminder:** Always run `git commit` and `git merge` with a git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._\n", - "\n", - "### Initialization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "beginning-cassette", - "metadata": {}, - "outputs": [], - "source": [ - "# check current directory with \"pwd\"\n", - "\n", - "# in case you are in the wrong directory, navigate to Exercise_4 using \"cd\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "ff78654b", - "metadata": {}, - "source": [ - "**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "developing-jamaica", - "metadata": {}, - "outputs": [], - "source": [ - "# source the helpers.sh file to be able to use its functions\n", - "source ../helpers.sh\n", - "# init exercise\n", - "init_exercise" - ] - }, - { - "cell_type": "markdown", - "id": "loaded-pontiac", - "metadata": {}, - "source": [ - "***\n", - "### Optional: clear notebook and restart\n", - "**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "individual-domain", - "metadata": {}, - "outputs": [], - "source": [ - "## only execute in case of (serious) trouble ##\n", - "## it will delete your entire beginners_git directory ##\n", - "reset" - ] - }, - { - "cell_type": "markdown", - "id": "boring-enzyme", - "metadata": {}, - "source": [ - "***\n", - "## Exercise\n", - "\n", - "### Practice typical Git workflow\n", - "\n", - "First, we will set up a simple Git repository for you using one of the helper functions:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "greenhouse-quest", - "metadata": {}, - "outputs": [], - "source": [ - "# this line will create the directory `conference_planning` and the empty schedule `conference_schedule.txt` in it\n", - "init_repo_empty_schedule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "massive-asbestos", - "metadata": {}, - "outputs": [], - "source": [ - "# init Git repository\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "prompt-looking", - "metadata": {}, - "outputs": [], - "source": [ - "# execute \"ls -a\" to also see the hidden git folder\n" - ] - }, - { - "cell_type": "markdown", - "id": "76a09714", - "metadata": {}, - "source": [ - "### Understanding *.gitignore*\n", - "\n", - "The *.gitignore* file is an essential and commonly used feature in Git. It specifies intentionally untracked files that Git should ignore. It's particularly useful for excluding files generated during execution or build processes—like log files, compiled code, or local configuration files—that don't need to be shared within the repository. Creating a *.gitignore* file and listing the file patterns to exclude achieves this.\n", - "\n", - "**Typical Ingredients of *.gitignore*:**\n", - "\n", - "Once your *.gitignore* is created, you can specify:\n", - "\n", - "- **Patterns**: Direct patterns such as *my_file_to_ignore.txt* to exclude specific files or *my_directory_to_ignore/* to exclude specific directories. For example, *.ipynb_checkpoints/* is often added to the *.gitignore* when working with Jupyter Notebooks to ignore checkpoint folders created during development.\n", - "- **Wildcards**: Broad patterns like `*.log` to exclude all log files created across the project.\n", - "- **Exceptions**: If you've used a wildcard but want to track specific files, precede the exception with `!`. For instance, *!important_log.log* ensures this file is tracked despite the `*.log` exclusion.\n", - "\n", - "Remember, the *.gitignore* file should be committed into your repository, so it is shared with other developers, ensuring that everyone working on the project is ignoring the same files.\n", - "\n", - "**Practical Application:**\n", - "\n", - "Now that you have seen and understood the concept of the *.gitignore* file, you can proceed with your exercises. At a certain point, after you run `git status`, you might notice a file named *.ipynb_checkpoints*. This is created by Jupyter Notebooks to save checkpoint files and it's exactly the type of content we aim to exclude from our Git repository, as it is specific to your local Jupyter Notebook environment. It thus presents a perfect opportunity to apply what you've just learned. Follow these steps to create a *.gitignore* and specify the patterns. Remember to add and commit your *.gitignore* after creating it. \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "08f11c4e", - "metadata": { - "vscode": { - "languageId": "shellscript" - } - }, - "outputs": [], - "source": [ - "# Create `.gitignore` and add the `.ipynb_checkpoints pattern` (Note: make sure you are in the conference_planning directory when running the following command)\n", - "echo \".ipynb_checkpoints/\" >> .gitignore\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b55e0f49", - "metadata": { - "vscode": { - "languageId": "shellscript" - } - }, - "outputs": [], - "source": [ - "# Add and commit your .gitignore\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "committed-brass", - "metadata": {}, - "source": [ - "### Go on with your Exercise\n", - "\n", - "Add events to the schedule.\n", - "\n", - "Remember to make any changes to the schedule directly in Jupyter Notebooks:\n", - " * Go to folder *beginners_git/conference_planning*\n", - " * Open *conference_schedule.txt*\n", - " * Change file\n", - "\n", - "**Don't forget to save your modifications before coming back!**\n", - "\n", - "Please use this way of editing files throughout the exercise.\n", - "\n", - "- Add a talk, coffee break, workshop" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "frank-responsibility", - "metadata": {}, - "outputs": [], - "source": [ - "# commit your changes\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "valid-wallpaper", - "metadata": {}, - "source": [ - "The workshop has been canceled and we will have a poster session instead.\n", - "\n", - "Adjust your document accordingly." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ranking-arrival", - "metadata": {}, - "outputs": [], - "source": [ - "# commit the adapted \"conference_schedule.txt\"\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "smart-craft", - "metadata": {}, - "source": [ - "We continue to plan. Add these three events to *conference_schedule.txt*:\n", - " * Lunch break\n", - " * Another talk\n", - " * Second poster session" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "mature-night", - "metadata": {}, - "outputs": [], - "source": [ - "# commit your changes\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "fifty-recall", - "metadata": {}, - "source": [ - "Check if all of your changes are really tracked by Git.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "polished-source", - "metadata": {}, - "outputs": [], - "source": [ - "# check Git status\n", - "\n", - "# check Git log\n" - ] - }, - { - "cell_type": "markdown", - "id": "floating-conditions", - "metadata": {}, - "source": [ - "If you don't have any untracked changes in your repository, proceed to the next part of this exercise.\n", - "\n", - "\n", - "\n", - "**It is late at night and your concentration is not very high...**\n", - "\n", - "By accident you delete all of your existing files..." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "integral-shaft", - "metadata": {}, - "outputs": [], - "source": [ - "# CAUTION: executing this panel deletes all files in the current directory\n", - "rm *" - ] - }, - { - "cell_type": "markdown", - "id": "miniature-humor", - "metadata": {}, - "source": [ - "Thanks to Git we can easily restore files, even if they are deleted." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f318c123", - "metadata": {}, - "outputs": [], - "source": [ - "# check Git status\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "useful-spotlight", - "metadata": {}, - "outputs": [], - "source": [ - "# restore deleted files\n" - ] - }, - { - "cell_type": "markdown", - "id": "greatest-classification", - "metadata": {}, - "source": [ - "As a next step, create a new branch and edit the schedule there, since we are not sure yet if Professor X will accept the talk in the morning. \n", - "\n", - "**Always make sure to reload your file before changing it**\n", - " * Change the talk to a workshop" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "purple-conspiracy", - "metadata": {}, - "outputs": [], - "source": [ - "# create new branch and adjust the schedule\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "trying-ideal", - "metadata": {}, - "outputs": [], - "source": [ - "# commit changes\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "determined-classification", - "metadata": {}, - "source": [ - "Switch back to branch *main* and create another branch on top of it.\n", - "We want to plan an evening activity but are not sure what it will be. Therefore, we create two branches with different activities." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "single-contribution", - "metadata": {}, - "outputs": [], - "source": [ - "# switch to main\n", - "\n", - "# create new branch and add an evening activity\n" - ] - }, - { - "cell_type": "markdown", - "id": "56b0e310", - "metadata": {}, - "source": [ - "Add an evening activity and commit the changes. Don't forget to reload your file before changing!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "minus-matrix", - "metadata": {}, - "outputs": [], - "source": [ - "# commit changes\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "major-implement", - "metadata": {}, - "source": [ - "Switch to branch *main* and create another branch on top of it, to add an alternative evening activity." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "abroad-ownership", - "metadata": {}, - "outputs": [], - "source": [ - "# switch to main branch\n", - "\n", - "# create new branch and add another evening activity\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "informative-infrared", - "metadata": {}, - "outputs": [], - "source": [ - "# commit changes\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "extreme-figure", - "metadata": {}, - "source": [ - "It's time to get an overview of what we just did.\n", - "Our repository has currently 4 branches (names may be different for your case):\n", - " * *main* (base version of all subsequent branches)\n", - " * *alternative_talk* (workshop instead of talk)\n", - " * *evening_activity* (First planned activity)\n", - " * *evening_activity_alternative* (Alternative activity)\n", - " \n", - "Ensure your repository contains the same amount of different branches." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "congressional-exception", - "metadata": {}, - "outputs": [], - "source": [ - "# display all branches of the Git repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "registered-england", - "metadata": {}, - "source": [ - "The talk in the morning has not been accepted.\n", - "Therefore merge the branch *alternative_talk* into *main*.\n", - "\n", - "**Remark:** Make sure you are in the *main* branch before starting the merge, because Git always merges a branch **into** your current branch.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "breeding-partition", - "metadata": {}, - "outputs": [], - "source": [ - "# merge schedule branch into the main branch\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "brown-northern", - "metadata": {}, - "outputs": [], - "source": [ - "# follow good practice and delete the merged branch\n" - ] - }, - { - "cell_type": "markdown", - "id": "certified-parks", - "metadata": {}, - "source": [ - "The last step of the planning is to choose one of the two evening activities.\n", - "Decide which one you prefer.\n", - "\n", - "Merge the corresponding branch into *main*.\n", - "\n", - "**Don't forget to add a commit message!**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "accepted-modification", - "metadata": {}, - "outputs": [], - "source": [ - "# merge your preferred evening activity into main\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "measured-corner", - "metadata": {}, - "outputs": [], - "source": [ - "# delete merged branch\n" - ] - }, - { - "cell_type": "markdown", - "id": "solid-monte", - "metadata": {}, - "source": [ - "There is one unused branch left in our repository.\n", - "We want to keep the repository clean and nice. So please delete the unmerged branch as well.\n", - "\n", - "**Remark:** Since we did not merge the remaining branch, it has to be done differently before. But don't worry, Git will tell you what to do." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "flush-alliance", - "metadata": {}, - "outputs": [], - "source": [ - "# delete unused branch\n" - ] - }, - { - "cell_type": "markdown", - "id": "quarterly-homework", - "metadata": {}, - "source": [ - "**Congrats, you already know the most essential Git commands for the local use of Git.**" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/Exercise_4_workflow_gitignore.md b/beginner/Exercise_4_workflow_gitignore.md new file mode 100644 index 0000000..10faf79 --- /dev/null +++ b/beginner/Exercise_4_workflow_gitignore.md @@ -0,0 +1,148 @@ +# Exercise 4 + +## Objective + * Practice the typical Git workflow + * Understand the function of a *.gitignore* file, and learn the steps involved in creating and configuring it within a Git repository. + +## Structure + +In this exercise, we won't be learning any new Git commands. Rather, we will review all the commands and workflows we learned in the previous exercises. We will do this by working on the *conference_schedule.txt* document and simulating a possible workflow. Since this is a review, there will be less explanation for that part of this exercise. + +In addition to that, we will explore a crucial aspect of Git: the *.gitignore* file. We'll learn how to create and configure this file to manage the files that Git should ignore, enhancing our typical workflow. + +## Helper Functions +The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with. + +For this exercise, we will use the following functions from this file: + * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work. + * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely. + * `init_repo_empty_schedule`: This will create the directory *conference_planning* and a file *conference_schedule.txt* with an empty schedule. + +## Remarks + +> **Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word. + +> **Note:** Some exercises may require the use of basic Unix commands. If you are unfamiliar with Unix systems, refer to the file [Basic Unix Commands](Unix_Commands.md) for a list of all necessary commands. + +If everything is still set up from the last exercise, you can continue with [this exercise](#exercise) directly. +Otherwise, please refer to the [Initialization from Exercise 1](Exercise_1_basic_commands.md#initialization). + +## Exercise + +### Understanding *.gitignore* + +The *.gitignore* file is an essential and commonly used feature in Git. It specifies intentionally untracked files that Git should ignore. It's particularly useful for excluding files generated during execution or build processes—like log files, compiled code, or local configuration files—that don't need to be shared within the repository. Creating a *.gitignore* file and listing the file patterns to exclude achieves this. + +**Typical Ingredients of *.gitignore*:** + +Once your *.gitignore* is created, you can specify: + +- **Patterns**: Direct patterns such as *my_file_to_ignore.txt* to exclude specific files or *my_directory_to_ignore/* to exclude specific directories. +- **Wildcards**: Broad patterns like `*.log` to exclude all log files created across the project. +- **Exceptions**: If you've used a wildcard but want to track specific files, precede the exception with `!`. For instance, *!important_log.log* ensures this file is tracked despite the `*.log` exclusion. + +Remember, the *.gitignore* file should be committed into your repository, so it is shared with other developers, ensuring that everyone working on the project is ignoring the same files. + +**Practical Application:** + +1. Navigate to the root of your *git-course* repository. + +2. Execute `ls -a` to also see the hidden Git folder. You should see the *.gitignore* file. Have a look into it. + +3. Run the *check_requirements.sh* file (as you should have done as preparation for the course): + +```bash +./check_requirements.sh +``` + +4. Check the status of your Git repository. You should now see the log file from running the requirement check. + +Log files are typically generated for debugging and monitoring purposes but are not meant to be part of the Git repository. Since they change frequently and can grow large, they are usually added to the *.gitignore* file to keep the repository clean and prevent unnecessary clutter. + +5. Add a wildcart to the *.gitignore* file to exclude all log files. + +6. Check the status of *git-course* repository. Does the log file still show up? + +Use *.gitignore* whenever files clutter your Git repository, but shouldn't be committed. + +### Practice typical Git workflow + +1. First, we will set up a simple Git repository for you using one of the helper functions. It will create the directory *conference_planning* and the empty schedule *conference_schedule.txt* in and navigate you to the folder. + +```bash +init_repo_empty_schedule +``` + +2. Initialise the folder as a Git repository. +3. Add and commit the *conference_schedule.txt* file. +4. Add a talk, coffee break, workshop to your schedule. +5. Add and commit your changes. +6. The workshop has been canceled and we will have a poster session instead. Adjust your document accordingly. +7. Add and commit the changes. +We continue to plan. +8. Add a lunch break, another talk and a second poster session to the schedule and commit your changes. +9. Check if all of your changes are really tracked by Git by checking the status und the history. + +If you don't have any untracked changes in your repository, proceed to the next part of this exercise. + + +### It is late at night and your concentration is not very high... + +1. By accident you delete all of your existing files... + + +```bash +# CAUTION: executing this panel deletes all files in the current directory +rm * +``` + +Thanks to Git we can easily restore files, even if they are deleted. + +2. Check the Git status. +3. Restore the deleted files + +### As a next step we will make changes on a different branch + +1. Create a new branch. +2. We are not sure yet if Professor X will accept the talk in the morning, therefore change the talk to a workhop on this branch as an alternative schedule. +3. Add and commit your changes. +4. No switch back to branch *main* and create another branch on top of it. + +We want to plan an evening activity but are not sure what it will be. Therefore, we create two branches with different activities. + +5. Create a new branch and add an evening activity. +6. Add and commit the change. + +7. Switch to branch *main* and create another branch on top of it, to add an alternative evening activity. + +It's time to get an overview of what we just did. + +Our repository should currently have four branches (names may be different for your case): + * *main* (base version of all subsequent branches) + * *alternative_talk* (workshop instead of talk) + * *evening_activity* (First planned activity) + * *evening_activity_alternative* (Alternative activity) + +8. Ensure your repository contains the same amount of different branches by displaying the available branches. + +The talk in the morning has finally been cancelled. + +9. Merge the branch containing the workshop instead of the talk into the *main* branch. + +**Remark:** Make sure you are in the *main* branch before starting the merge, because Git always merges a branch **into** your current branch. + +10. Follow good practice and delete the merged branch. + +The last step of the planning is to choose one of the two evening activities. +Decide which one you prefer. + +11. Merge your preferred evening activity into the *main* branch. + +12. Delete the merge branch. + +There is one unused branch left in our repository. +13. We want to keep the repository clean and nice. So please delete the unmerged branch as well. + +**Remark:** Since we did not merge the remaining branch, it has to be done differently before. But don't worry, Git will tell you what to do. + +**Congrats, you already know the most essential Git commands for the local use of Git.** \ No newline at end of file diff --git a/beginner/Exercise_5/Exercise_5.ipynb b/beginner/Exercise_5/Exercise_5.ipynb deleted file mode 100644 index da180b8..0000000 --- a/beginner/Exercise_5/Exercise_5.ipynb +++ /dev/null @@ -1,338 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "bearing-impact", - "metadata": {}, - "source": [ - "## Exercise 5\n", - "\n", - "## Objective\n", - "* Add a remote repository\n", - "* Explore remote branches\n", - "* Exchange information with a remote repository\n", - "\n", - "## Structure\n", - "In this exercise we will start to learn about working with remote repositories. A remote repository is usually stored online at GitHub or GitLab. For simplicity, the remote repository for this exercise will be located in the same directory locally, but the workflow would be basically the same.\n", - "\n", - "## Helper Functions\n", - "The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with.\n", - "\n", - "For this exercise, we will use the following functions from this file:\n", - " * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work.\n", - " * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely.\n", - " * `init_simple_repo_remote`: This will create the same simple repository as before, along with a second repository to be used as a remote.\n", - "\n", - "## Remarks\n", - "_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._\n", - "\n", - "_**Reminder:** Always run `git commit` and `git merge` with a git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._\n", - "\n", - "### Initialization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "infrared-dayton", - "metadata": {}, - "outputs": [], - "source": [ - "# check current directory with \"pwd\"\n", - "\n", - "# in case you are in the wrong directory, navigate to Exercise_5 using \"cd\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "0eed24cf", - "metadata": {}, - "source": [ - "**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "specialized-edition", - "metadata": {}, - "outputs": [], - "source": [ - "# source the helpers.sh file to be able to use its functions\n", - "source ../helpers.sh\n", - "# init exercise\n", - "init_exercise" - ] - }, - { - "cell_type": "markdown", - "id": "atomic-chair", - "metadata": {}, - "source": [ - "***\n", - "### Optional: clear notebook and restart\n", - "**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "educational-capture", - "metadata": {}, - "outputs": [], - "source": [ - "## only execute in case of (serious) trouble ##\n", - "## it will delete your entire beginners_git directory ##\n", - "reset" - ] - }, - { - "cell_type": "markdown", - "id": "returning-reality", - "metadata": {}, - "source": [ - "***\n", - "## Exercise\n", - "\n", - "In this exercise, we will use the same simple repository that we used before, along with a remote repository. Let's initialize it with our helper function." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "excellent-anniversary", - "metadata": {}, - "outputs": [], - "source": [ - "# this line sets up a simple Git repository along with a remote Git repository\n", - "init_simple_repo_remote" - ] - }, - { - "cell_type": "markdown", - "id": "unusual-perfume", - "metadata": {}, - "source": [ - "### Add a remote repository\n", - "\n", - "Let's add a remote repository to our local repository. \n", - "\n", - "The setup script has already created one for you to use, which you can find here: \n", - "\n", - "**../conference_planning_remote**\n", - "\n", - "Use the above line as the *remote_path* to the remote repository." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "discrete-affiliation", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git remote add \" to add the remote \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "complicated-fifth", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git remote -v\" to check that the remote was added correctly\n" - ] - }, - { - "cell_type": "markdown", - "id": "front-custom", - "metadata": {}, - "source": [ - "The output should look something like this:\n", - "```\n", - "my_remote ../conference_planning_remote (fetch)\n", - "my_remote ../conference_planning_remote (push)\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "crude-intensity", - "metadata": {}, - "source": [ - "### Get information from remote\n", - "\n", - "So far we have only given our local repository the location of the remote repository. Now, we want to get the information from the remote repository." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "viral-examination", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git fetch \" to get information from the remote\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "disciplinary-packaging", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git branch -a\" to view ALL of the branches in your local repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "narrow-confidence", - "metadata": {}, - "source": [ - "The output should look like this:\n", - "```\n", - "* main\n", - " remotes/my_remote/main\n", - " remotes/my_remote/updated_schedules\n", - "```\n", - "\n", - "You can see that you now have a local branch (*main*), and remote branches (*remotes/\\/\\*).\n", - "### Add remote branch to local repository and make changes\n", - "\n", - "The remote repository has a branch called *updated_schedules*.\n", - "Let's check out this branch to work on it. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "limiting-snowboard", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git switch updated_schedules\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "automatic-underground", - "metadata": {}, - "source": [ - "The output should look like this:\n", - "```\n", - "branch 'updated_schedules' set up to track remote branch 'updated_schedules' from 'my_remote/updated_schedules'.\n", - "Switched to a new branch 'updated_schedules'\n", - "```\n", - "\n", - "Git has automatically created a local branch in our local repository that tracks the remote branch from the remote repository.\n", - "\n", - "Now let's make a change to the *updated_schedules* branch.\n", - "Remember to make all changes to the schedules directly in Jupyter Notebooks:\n", - " * Go to folder *beginners_git/conference_planning*\n", - " * Open *schedule_day1.txt*\n", - " * Add more information to your schedule, i.e. talks, workshops, etc.\n", - "\n", - "**Don't forget to save your changes before you come back!**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cognitive-frederick", - "metadata": {}, - "outputs": [], - "source": [ - "# add and commit your changes\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "destroyed-armenia", - "metadata": {}, - "outputs": [], - "source": [ - "# check the status of your repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "utility-swaziland", - "metadata": {}, - "source": [ - "The output should look like this:\n", - "```\n", - "On branch updated_schedules\n", - "Your branch is ahead of 'my_remote/updated_schedules' by 1 commit.\n", - " (use \"git push\" to publish your local commits)\n", - "\n", - "nothing to commit, working tree clean\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "aboriginal-cowboy", - "metadata": {}, - "source": [ - "### Send information to remote repository\n", - "\n", - "Finally, we want to commit our changes back to the remote repository. To commit to a remote repository, use the `git push` command." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "liquid-andrew", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git push\" \n" - ] - }, - { - "cell_type": "markdown", - "id": "statutory-naples", - "metadata": {}, - "source": [ - "The output should look something like this:\n", - "```\n", - "Enumerating objects: 5, done.\n", - "Counting objects: 100% (5/5), done.\n", - "Delta compression using up to 8 threads\n", - "Compressing objects: 100% (3/3), done.\n", - "Writing objects: 100% (3/3), 350 bytes | 350.00 KiB/s, done.\n", - "Total 3 (delta 1), reused 0 (delta 0), pack-reused 0\n", - "To ../conference_planning_remote\n", - " 1dacf13..80e64e8 updated_schedules -> updated_schedules\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "c42c9642", - "metadata": {}, - "source": [ - "**Congrats, you now also know the most essential Git commands for the _remote_ use of Git.**" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/Markdowns/Exercise_5.md b/beginner/Exercise_5_remotes.md similarity index 62% rename from beginner/Markdowns/Exercise_5.md rename to beginner/Exercise_5_remotes.md index a034603..d49172b 100644 --- a/beginner/Markdowns/Exercise_5.md +++ b/beginner/Exercise_5_remotes.md @@ -1,4 +1,4 @@ -## Exercise 5 +# Exercise 5 ## Objective * Add a remote repository @@ -16,50 +16,31 @@ For this exercise, we will use the following functions from this file: * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely. * `init_simple_repo_remote`: This will create the same simple repository as before, along with a second repository to be used as a remote. -## Remarks -_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._ +## Remarks -_**Reminder:** Always run `git commit` and `git merge` with a git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._ +> **Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word. -### Initialization +> **Note:** Some exercises may require the use of basic Unix commands. If you are unfamiliar with Unix systems, refer to the file [Basic Unix Commands](Unix_Commands.md) for a list of all necessary commands. +If everything is still set up from the last exercise, you can continue with [this exercise](#exercise) directly. +Otherwise, please refer to the [Initialization from Exercise 1](Exercise_1_basic_commands.md#initialization). -```bash -# check current directory with "pwd" - -# in case you are in the wrong directory, navigate to Exercise_5 using "cd" - -``` - -**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.** - - -```bash -# source the helpers.sh file to be able to use its functions -source ../helpers.sh -# init exercise -init_exercise -``` - -*** -### Optional: clear notebook and restart -**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.** +### Optional: restart exercise repo +⚠️ **In case you messed up somehow, execute the `reset` function. Check the [Helper Functions](#helper-functions) section above for more explanation.** ```bash -## only execute in case of (serious) trouble ## +## only execute this in case of (serious) trouble ## ## it will delete your entire beginners_git directory ## reset ``` -*** ## Exercise -In this exercise, we will use the same simple repository that we used before, along with a remote repository. Let's initialize it with our helper function. +In this exercise, we will use the same simple repository that we used before, along with a remote repository. Let's initialize it with our helper function. The following will set up a simple Git repository along with a remote Git repository ```bash -# this line sets up a simple Git repository along with a remote Git repository init_simple_repo_remote ``` @@ -69,21 +50,15 @@ Let's add a remote repository to our local repository. The setup script has already created one for you to use, which you can find here: -**../conference_planning_remote** - -Use the above line as the *remote_path* to the remote repository. +**../conference_planning_remote** (imagine this path to be the path to a repository on GitHub or GitLab) +1. Use the above line as the *remote_path* to the remote repository and choose a name for your remote repository: ```bash -# use "git remote add " to add the remote - +git remote add ``` - -```bash -# use "git remote -v" to check that the remote was added correctly - -``` +2. Use `git remote -v` to check that the remote was added correctly. The output should look something like this: ``` @@ -95,17 +70,9 @@ my_remote ../conference_planning_remote (push) So far we have only given our local repository the location of the remote repository. Now, we want to get the information from the remote repository. +1. Use `git fetch ` to get information from the remote. -```bash -# use "git fetch " to get information from the remote - -``` - - -```bash -# use "git branch -a" to view ALL of the branches in your local repository - -``` +2. Use `git branch -a` to view ALL of the branches in your local repository. The output should look like this: ``` @@ -115,16 +82,13 @@ The output should look like this: ``` You can see that you now have a local branch (*main*), and remote branches (*remotes/\/\*). + ### Add remote branch to local repository and make changes The remote repository has a branch called *updated_schedules*. Let's check out this branch to work on it. - -```bash -# use "git switch updated_schedules" - -``` +1. Switch to branch *updated_schedules*. The output should look like this: ``` @@ -134,26 +98,9 @@ Switched to a new branch 'updated_schedules' Git has automatically created a local branch in our local repository that tracks the remote branch from the remote repository. -Now let's make a change to the *updated_schedules* branch. -Remember to make all changes to the schedules directly in Jupyter Notebooks: - * Go to folder *beginners_git/conference_planning* - * Open *schedule_day1.txt* - * Add more information to your schedule, i.e. talks, workshops, etc. - -**Don't forget to save your changes before you come back!** - - -```bash -# add and commit your changes - - -``` - - -```bash -# check the status of your repository - -``` +2. Let's make a change to the *updated_schedules* branch. +3. Add and commit your changes. +4. Check the status of your repository. The output should look like this: ``` @@ -168,11 +115,7 @@ nothing to commit, working tree clean Finally, we want to commit our changes back to the remote repository. To commit to a remote repository, use the `git push` command. - -```bash -# use "git push" - -``` +1. Push commited changes to remote branch. The output should look something like this: ``` @@ -186,4 +129,4 @@ To ../conference_planning_remote 1dacf13..80e64e8 updated_schedules -> updated_schedules ``` -**Congrats, you now also know the most essential Git commands for the _remote_ use of Git.** +**Congrats, you now also know the most essential Git commands for the _remote_ use of Git.** \ No newline at end of file diff --git a/beginner/Exercise_6/Exercise_6.ipynb b/beginner/Exercise_6/Exercise_6.ipynb deleted file mode 100644 index 68133be..0000000 --- a/beginner/Exercise_6/Exercise_6.ipynb +++ /dev/null @@ -1,649 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "bearing-impact", - "metadata": {}, - "source": [ - "## Exercise 6\n", - "\n", - "## Objective\n", - " * Learn how to deal with merge conflicts:\n", - " * Undo merge\n", - " * Choose preferred version\n", - " * Modify file directly\n", - " \n", - "## Structure\n", - "\n", - "In this exercise, we will change the same file on different branches in a way that causes a merge conflict. We will also have to deal with a merge request when trying to pull from a remote repository because \"someone else\" made a conflicting change remotely.\n", - "\n", - "## Helper Functions\n", - "The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with.\n", - "\n", - "For this exercise, we will use the following functions from this file:\n", - " * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work.\n", - " * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely.\n", - " * `init_repo_remote`: This will set up a Git repository with a first version of *schedule_day1.txt* and a remote repository containing the same version of *schedule_day1.txt* on a different branch called *updated_schedules*.\n", - " * `commit_to_remote_by_third_party`: This will make a commit to the remote Git repository to create an artificial merge conflict when pulling.\n", - "\n", - "## Remarks\n", - "_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._\n", - "\n", - "_**Reminder:** Always run `git commit` and `git merge` with a git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._\n", - "\n", - "### Initialization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "infrared-dayton", - "metadata": {}, - "outputs": [], - "source": [ - "# check current directory with \"pwd\"\n", - "\n", - "# in case you are in the wrong directory, navigate to Exercise_6 using \"cd\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "72d291f1", - "metadata": {}, - "source": [ - "**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "specialized-edition", - "metadata": {}, - "outputs": [], - "source": [ - "# source the helpers.sh file to be able to use its functions\n", - "source ../helpers.sh\n", - "# init exercise\n", - "init_exercise" - ] - }, - { - "cell_type": "markdown", - "id": "atomic-chair", - "metadata": {}, - "source": [ - "***\n", - "### Optional: clear notebook and restart\n", - "**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "educational-capture", - "metadata": {}, - "outputs": [], - "source": [ - "## only execute in case of (serious) trouble ##\n", - "## it will delete your entire beginners_git directory ##\n", - "reset" - ] - }, - { - "cell_type": "markdown", - "id": "returning-reality", - "metadata": {}, - "source": [ - "***\n", - "## Exercise\n", - "\n", - "In this exercise we are going to use a repository together with a remote repository containing the file _schedule_day1.txt_. Let's initialize it with our helper function." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "excellent-anniversary", - "metadata": {}, - "outputs": [], - "source": [ - "# this line will set up a local and a remote Git repository\n", - "init_repo_remote" - ] - }, - { - "cell_type": "markdown", - "id": "3a32a9d8", - "metadata": {}, - "source": [ - "### Now let's make a change in the schedule and commit it\n", - "Remember to do all modifications of the schedules directly via Jupyter Notebooks:\n", - " * Go to folder *beginners_git/conference_planning*\n", - " * Open _schedule_day1.txt_\n", - " * Change the workshop to a second poster session" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "765eca4c", - "metadata": {}, - "outputs": [], - "source": [ - "# Change the workshop to a poster session and commit\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "unusual-perfume", - "metadata": {}, - "source": [ - "### Add a remote repository\n", - "\n", - "Let's add the remote repository to our local repository as we did in the previous exercise.\n", - "\n", - "The setup script has already created one for you at: \n", - "\n", - "**../conference_planning_remote**\n", - "\n", - "Use the above line as the *remote_path* to the remote repository." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "discrete-affiliation", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git remote add \" to add the remote \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "complicated-fifth", - "metadata": {}, - "outputs": [], - "source": [ - "# Get information from remote branch with \"git fetch \"\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "eb78f1fe", - "metadata": {}, - "outputs": [], - "source": [ - "# Check which branches are available\n" - ] - }, - { - "cell_type": "markdown", - "id": "bb0bba96", - "metadata": {}, - "source": [ - "### Now make a different change in the same file on the _updated_schedules_ branch\n", - " * Switch to the *updated_schedules* branch\n", - " * Change the workshop to a talk in *beginners_git/conference_planning/schedule_day1.txt*\n", - " * Commit your changes" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9f3a660d", - "metadata": {}, - "outputs": [], - "source": [ - "# Switch to updated_schedules\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "limiting-snowboard", - "metadata": {}, - "outputs": [], - "source": [ - "# Change workshop to talk and commit\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "ef95def7", - "metadata": {}, - "source": [ - "### Merge the *updated_schedules* branch into the *main* branch\n", - "We have decided to use the schedule on the *updated_schedules* branch. So we want to merge that branch into the *main* branch.\n", - "* Switch to *main* branch\n", - "* Merge *updated_schedules* into *main* branch" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8832fdb5", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# Go to the main branch\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "165265a6", - "metadata": {}, - "outputs": [], - "source": [ - "# Merge the updated_schedules branch into the main branch\n", - "# make sure to always add a commit message when merging with \"-m \"\n" - ] - }, - { - "cell_type": "markdown", - "id": "b1f0a8af-8421-403f-a724-5fd4f845ab11", - "metadata": {}, - "source": [ - "### Solve merge conflict\n", - "If you've done everything \"right\", something went \"wrong\" and the output should look like this:\n", - "\n", - "```\n", - "CONFLICT (content): Merge conflict in schedule_day1.txt\n", - "Automatic merge failed; fix conflicts and then commit the result.\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "5ebdc8d4-57c3-4fae-9f80-1f748c379dcd", - "metadata": {}, - "source": [ - "It looks like we ran into a merge conflict. This happened because we made changes on the *main* branch and the *updated_schedules* branch at the same part of the file. Git doesn't know which changes it should accept. Let's see how to fix this. \n", - "\n", - "Have a look at the file *schedule_day1.txt*. You will see something like this:\n", - "\n", - "``` \n", - "<<<<<<< HEAD\n", - "13:30-15:00: Poster session\n", - "=======\n", - "13:30-15:00: Talk professor C.\n", - ">>>>>>> updated_schedules \n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "a4a19cb2-7551-4394-97f0-9a9b226685d4", - "metadata": {}, - "source": [ - "The top line is the HEAD, referring to the branch you are currently on (here *main*), and the second line refers to the branch you wanted to merge (here *updated_schedules*).\n", - "\n", - "Here are two ways to resolve a merge conflict:\n", - "\n", - "1. **Adjust the file directly:**\n", - "\n", - " * Edit the file to resolve the conflict: You can adjust the file directly and delete the lines, which were added by the merge conflict except the lines you want to keep. Now the merge conflict is resolved.\n", - "\n", - " * Save your changes: After you've resolved all conflicts in the file, don't forget to save your changes.\n", - "\n", - " * Add your changes: Use `git add` to stage the resolved changes within _schedule_day1.txt_.\n", - "\n", - " * Commit your changes: Commiting your changes will finalize the merge process that was interrupted by the conflict.\n", - "\n", - "2. **Simplifying Conflict Resolution with `git restore`**\n", - "\n", - " Sometimes, you'll find that the entire version of the file from one branch is preferred over the other. In such cases, you can bypass manual edits by leveraging `git restore` to quickly choose between the version on your current branch (HEAD, referred to as _ours_) and the version from the branch you're merging from (_theirs_).\n", - "\n", - " * To adopt the version from your current branch (HEAD), use the command: \n", - " ```git restore schedule_day1.txt --ours```\n", - " \n", - " * Conversely, to accept the version from the merging branch, switch to: \n", - " ```git restore schedule_day1.txt --theirs```\n", - " \n", - " These commands replace the conflicted file in your working directory with the selected version. It's important to understand that `git restore` directly overwrites the file content, so use it when you're certain of wanting to keep only one branch's changes.\n", - "\n", - " After restoring the file:\n", - "\n", - " * Add your changes: Use `git add` to stage the resolved file within _schedule_day1.txt_.\n", - "\n", - " * Commit your changes: Commiting your changes will finalize the merge process that was interrupted by the conflict.\n", - "\n", - "\n", - "**Important note when dealing with merge conflicts**: After resolving the conflict, **no new merge command is required**. The original merge operation was paused, not stopped, when the conflict was detected. By resolving the conflict and committing the changes, you are completing the paused merge process.\n", - "\n", - "**Abort merge**:\n", - "\n", - "If you're afraid that everything is screwed up and you don't know what to do, just run ```git merge --abort``` and everything will be back to where it was before you tried to merge.\n", - "\n", - "Let's deal with the merge conflict!" - ] - }, - { - "cell_type": "markdown", - "id": "395f79a4", - "metadata": {}, - "source": [ - "### Abort merge" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f07c45df", - "metadata": {}, - "outputs": [], - "source": [ - "# Abort the merge commit and check if the file is set back to its previous version\n" - ] - }, - { - "cell_type": "markdown", - "id": "f5fd27cd", - "metadata": {}, - "source": [ - "### 1) Edit file directly to resolve conflict\n", - "Create the same merge conflict again by trying to merge the *updated_schedules* branch into the *main* branch." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3118e833", - "metadata": {}, - "outputs": [], - "source": [ - "# Merge again\n" - ] - }, - { - "cell_type": "markdown", - "id": "a860a033", - "metadata": {}, - "source": [ - "Now go to the file and select the version you want. To do this, remove all of the conflict markers from the file (<<<<<<< HEAD, =======, >>>>>>> updated_schedules) and the lines belonging to *HEAD* or the merging branch (*updated_schedules*) depending on which solution you want to keep.\n", - "\n", - "Stage the file once you have resolved the conflict with `git add`. Staging the file tells Git that the conflicts have been resolved. Note that Git does not check the file for conflict tags; it trusts you that you to have removed them all, so you need to be sure.\n", - "* Go to the conflicting file and delete the appropriate lines (don't forget saving)\n", - "* Stage the adapted file\n", - "* Commit merge" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5cc018dd", - "metadata": {}, - "outputs": [], - "source": [ - "# Stage schedule_day1.txt\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "efac3373", - "metadata": {}, - "outputs": [], - "source": [ - "# Finalize merge commit by running \"git commit\" (don't forget to add a commit message)\n" - ] - }, - { - "cell_type": "markdown", - "id": "3b65883f", - "metadata": {}, - "source": [ - "### 2) Restore preferred version from command line\n", - "First, we need to create a new conflict. To do this, go to the *main* and *updated_schedules* branches, respectively, and make different changes on the SAME line. Don't forget to commit the changes before switching between the branches." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "32de4086", - "metadata": {}, - "outputs": [], - "source": [ - "# Make a change to the schedule and commit it to the main branch\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "761999ea", - "metadata": {}, - "outputs": [], - "source": [ - "# Switch to the updated_schedules branch\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b1352ccc", - "metadata": {}, - "outputs": [], - "source": [ - "# Make a change at the SAME line and commit\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "20afb074", - "metadata": {}, - "outputs": [], - "source": [ - "# Go back to the main branch and try to merge the updated_schedules branch\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "58fe9568", - "metadata": {}, - "source": [ - "Now try to solve the merge conflict with ```git restore schedule_day1.txt --theirs/ours```." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cb2c271a", - "metadata": {}, - "outputs": [], - "source": [ - "# Restore the version of your favorite branch\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e1a4bcd9", - "metadata": {}, - "outputs": [], - "source": [ - "# Add and commit your favorite solution\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "20bc5bca", - "metadata": {}, - "source": [ - "### Merge conflict when trying to pull remote branch\n", - "We will now learn how to deal with another type of merge conflict that can easily occur when working with remote branches that other people are working on at the same time.\n", - "\n", - "To clean things up, let's first switch to the *updated_schedules* branch and push our latest commits to the remote branch." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "81486f4d", - "metadata": {}, - "outputs": [], - "source": [ - "# Switch to updated_schedules\n" - ] - }, - { - "cell_type": "markdown", - "id": "a0729d3f", - "metadata": {}, - "source": [ - "As you can see from the Git message, we are ahead of the remote branch. So before we continue, we want to push our local changes." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4b3e5577", - "metadata": {}, - "outputs": [], - "source": [ - "# Push changes to remote branch\n" - ] - }, - { - "cell_type": "markdown", - "id": "21dfdb2b", - "metadata": {}, - "source": [ - "Now change the first event to \"Introduction talk\" in _/conference_planning/schedule_day1.txt_ and commit." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aef5c7ae", - "metadata": {}, - "outputs": [], - "source": [ - "# Change the first event to \"Introduction\" and commit your changes\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "c5b0d1f6", - "metadata": {}, - "source": [ - "What we didn't realize is that someone changed something on the remote branch while we were working on the file. If we now try to pull the remote branch, we will run into a merge conflict.\n", - "\n", - "To mimic a person making changes to the same file at the same time, we use another helper function." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "66f617f5", - "metadata": {}, - "outputs": [], - "source": [ - "# Run helper function to commit to the same file remotely\n", - "commit_to_remote_by_third_party" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0c247138", - "metadata": {}, - "outputs": [], - "source": [ - "# Make sure you are on the updated_schedules branch and try to pull with \"git pull\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "c1eb1c0a", - "metadata": {}, - "source": [ - "Unless you already set how to pull in your Git config, you will get a message like this:\n", - "```\n", - "hint: You have divergent branches and need to specify how to reconcile them.\n", - "hint: You can do so by running one of the following commands sometime before\n", - "hint: your next pull:\n", - "hint: \n", - "hint: git config pull.rebase false # merge\n", - "hint: git config pull.rebase true # rebase\n", - "hint: git config pull.ff only # fast-forward only\n", - "hint: \n", - "hint: You can replace \"git config\" with \"git config --global\" to set a default\n", - "hint: preference for all repositories. You can also pass --rebase, --no-rebase,\n", - "hint: or --ff-only on the command line to override the configured default per\n", - "hint: invocation.\n", - "```\n", - "Read the hints and the explanations below carefully and choose your preferred setting.\n", - "\n", - "`# merge`: This option will handle pull requests the same way as when merging a branch, i.e., the merge will not be automatically committed.\n", - "\n", - "`# rebase`: This option will commit a merge directly in case there are no conflicts. Otherwise you will have to solve the conflicts before continuing (Git will tell you all necessary steps)\n", - "\n", - "`# fast-forward only`: This option will only do a merge in case there are no conflicts, otherwise nothing will be done (we do not recommend this option, to undo it, you need to run `git config pull.ff false`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "37e23497", - "metadata": {}, - "outputs": [], - "source": [ - "# Choose your preferred way of pulling\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "137f6c9a", - "metadata": {}, - "outputs": [], - "source": [ - "# Now pull again\n" - ] - }, - { - "cell_type": "markdown", - "id": "9264d18d", - "metadata": {}, - "source": [ - "Again, you ran into a merge conflict. You are now ready to solve the conflict yourself!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d611139b", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/Markdowns/Exercise_6.md b/beginner/Exercise_6_merge_conflicts.md similarity index 61% rename from beginner/Markdowns/Exercise_6.md rename to beginner/Exercise_6_merge_conflicts.md index c01cda4..2cebffd 100644 --- a/beginner/Markdowns/Exercise_6.md +++ b/beginner/Exercise_6_merge_conflicts.md @@ -1,4 +1,4 @@ -## Exercise 6 +# Exercise 6 ## Objective * Learn how to deal with merge conflicts: @@ -19,43 +19,15 @@ For this exercise, we will use the following functions from this file: * `init_repo_remote`: This will set up a Git repository with a first version of *schedule_day1.txt* and a remote repository containing the same version of *schedule_day1.txt* on a different branch called *updated_schedules*. * `commit_to_remote_by_third_party`: This will make a commit to the remote Git repository to create an artificial merge conflict when pulling. -## Remarks -_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._ +## Remarks -_**Reminder:** Always run `git commit` and `git merge` with a git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._ +> **Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word. -### Initialization +> **Note:** Some exercises may require the use of basic Unix commands. If you are unfamiliar with Unix systems, refer to the file [Basic Unix Commands](Unix_Commands.md) for a list of all necessary commands. +If everything is still set up from the last exercise, you can continue with [this exercise](#exercise) directly. +Otherwise, please refer to the [Initialization from Exercise 1](Exercise_1_basic_commands.md#initialization). -```bash -# check current directory with "pwd" - -# in case you are in the wrong directory, navigate to Exercise_6 using "cd" - -``` - -**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.** - - -```bash -# source the helpers.sh file to be able to use its functions -source ../helpers.sh -# init exercise -init_exercise -``` - -*** -### Optional: clear notebook and restart -**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.** - - -```bash -## only execute in case of (serious) trouble ## -## it will delete your entire beginners_git directory ## -reset -``` - -*** ## Exercise In this exercise we are going to use a repository together with a remote repository containing the file _schedule_day1.txt_. Let's initialize it with our helper function. @@ -66,18 +38,11 @@ In this exercise we are going to use a repository together with a remote reposit init_repo_remote ``` -### Now let's make a change in the schedule and commit it -Remember to do all modifications of the schedules directly via Jupyter Notebooks: - * Go to folder *beginners_git/conference_planning* - * Open _schedule_day1.txt_ - * Change the workshop to a second poster session - +Let's make a change in the schedule and commit it. -```bash -# Change the workshop to a poster session and commit +1. Change the workshop to a poster session in *schedule_day1.txt*. - -``` +2. Add and commit the file. ### Add a remote repository @@ -89,59 +54,24 @@ The setup script has already created one for you at: Use the above line as the *remote_path* to the remote repository. +1. Add the remote to your repository (`git remote add `) -```bash -# use "git remote add " to add the remote - -``` - - -```bash -# Get information from remote branch with "git fetch " - -``` +2. Get information from remote branch with `git fetch `. - -```bash -# Check which branches are available - -``` +3. Check which branches are available on the remote (`git branch -a`). ### Now make a different change in the same file on the _updated_schedules_ branch - * Switch to the *updated_schedules* branch - * Change the workshop to a talk in *beginners_git/conference_planning/schedule_day1.txt* - * Commit your changes - - -```bash -# Switch to updated_schedules - -``` - -```bash -# Change workshop to talk and commit +1. Switch to the *updated_schedules* branch. +2. Change the workshop to a talk in *schedule_day1.txt*. +3. Add and commit your changes. -``` - ### Merge the *updated_schedules* branch into the *main* branch We have decided to use the schedule on the *updated_schedules* branch. So we want to merge that branch into the *main* branch. -* Switch to *main* branch -* Merge *updated_schedules* into *main* branch - - -```bash -# Go to the main branch - -``` - -```bash -# Merge the updated_schedules branch into the main branch -# make sure to always add a commit message when merging with "-m " - -``` +1. Switch to *main* branch. +2. Merge the *updated_schedules* branch into the *main* branch. ### Solve merge conflict If you've done everything "right", something went "wrong" and the output should look like this: @@ -171,8 +101,6 @@ Here are two ways to resolve a merge conflict: * Edit the file to resolve the conflict: You can adjust the file directly and delete the lines, which were added by the merge conflict except the lines you want to keep. Now the merge conflict is resolved. - * Save your changes: After you've resolved all conflicts in the file, don't forget to save your changes. - * Add your changes: Use `git add` to stage the resolved changes within _schedule_day1.txt_. * Commit your changes: Commiting your changes will finalize the merge process that was interrupted by the conflict. @@ -206,128 +134,47 @@ Let's deal with the merge conflict! ### Abort merge +1. Abort the merge. -```bash -# Abort the merge commit and check if the file is set back to its previous version +### Adjust the file directly to resolve conflict +1. Create the same merge conflict again by trying to merge the *updated_schedules* branch into the *main* branch. -``` +2. Now go to the file and select the version you want. To do this, remove all of the conflict markers from the file (*<<<<<<< HEAD, =======*, *>>>>>>> updated_schedules*) and the lines belonging to *HEAD* or the merging branch (*updated_schedules*) depending on which solution you want to keep. -### 1) Edit file directly to resolve conflict -Create the same merge conflict again by trying to merge the *updated_schedules* branch into the *main* branch. +3. Stage the file with `git add` to tell Git that the conflicts have been resolved. Note that Git does not check the file for conflict tags; it trusts you that you to have removed them all, so you need to be sure. +4. Finalize the merge by running `git commit`. -```bash -# Merge again - -``` - -Now go to the file and select the version you want. To do this, remove all of the conflict markers from the file (<<<<<<< HEAD, =======, >>>>>>> updated_schedules) and the lines belonging to *HEAD* or the merging branch (*updated_schedules*) depending on which solution you want to keep. - -Stage the file once you have resolved the conflict with `git add`. Staging the file tells Git that the conflicts have been resolved. Note that Git does not check the file for conflict tags; it trusts you that you to have removed them all, so you need to be sure. -* Go to the conflicting file and delete the appropriate lines (don't forget saving) -* Stage the adapted file -* Commit merge - - -```bash -# Stage schedule_day1.txt - -``` - - -```bash -# Finalize merge commit by running "git commit" (don't forget to add a commit message) - -``` - -### 2) Restore preferred version from command line +### Restore preferred version from command line First, we need to create a new conflict. To do this, go to the *main* and *updated_schedules* branches, respectively, and make different changes on the SAME line. Don't forget to commit the changes before switching between the branches. - -```bash -# Make a change to the schedule and commit it to the main branch - - -``` - - -```bash -# Switch to the updated_schedules branch - -``` - - -```bash -# Make a change at the SAME line and commit - - -``` - - -```bash -# Go back to the main branch and try to merge the updated_schedules branch - - -``` - -Now try to solve the merge conflict with ```git restore schedule_day1.txt --theirs/ours```. - - -```bash -# Restore the version of your favorite branch - -``` - - -```bash -# Add and commit your favorite solution - - -``` +1. Switch to the *updated_schedules* branch and make a change to the file. +2. Add and commit the change and switch back to the *main* branch. +3. Make a change to the SAME line of the file as you did on the *updated_schedules* branch. +4. Add and commit your changes. +5. Try to merge the *updated_schedules* branch into the *main* branch. +6. Solve the merge conflict with `git restore schedule_day1.txt --theirs/ours` (choose your preferred version). +7. Add your solution to the merge. +8. Finalize merge by committing. ### Merge conflict when trying to pull remote branch We will now learn how to deal with another type of merge conflict that can easily occur when working with remote branches that other people are working on at the same time. To clean things up, let's first switch to the *updated_schedules* branch and push our latest commits to the remote branch. - -```bash -# Switch to updated_schedules - -``` - +1. Switch to the *updated_schedules* branch. As you can see from the Git message, we are ahead of the remote branch. So before we continue, we want to push our local changes. - - -```bash -# Push changes to remote branch - -``` - -Now change the first event to "Introduction talk" in _/conference_planning/schedule_day1.txt_ and commit. - - -```bash -# Change the first event to "Introduction" and commit your changes - - -``` +2. Push changes to the remote branch with `git push`. +3. Now change the first event to "Introduction talk" in *schedule_day1.txt* and commit the change. What we didn't realize is that someone changed something on the remote branch while we were working on the file. If we now try to pull the remote branch, we will run into a merge conflict. -To mimic a person making changes to the same file at the same time, we use another helper function. - - +4. To mimic a person making changes to the same file at the same time, we use another helper function. Run the following to do so: ```bash -# Run helper function to commit to the same file remotely commit_to_remote_by_third_party ``` - -```bash -# Make sure you are on the updated_schedules branch and try to pull with "git pull" - -``` +5. Now make sure you are on the *updated_schedules* branch and try to pull with `git pull`. Unless you already set how to pull in your Git config, you will get a message like this: ``` @@ -352,21 +199,6 @@ Read the hints and the explanations below carefully and choose your preferred se `# fast-forward only`: This option will only do a merge in case there are no conflicts, otherwise nothing will be done (we do not recommend this option, to undo it, you need to run `git config pull.ff false`) +6. Choose and set your preferred way of pulling. -```bash -# Choose your preferred way of pulling - -``` - - -```bash -# Now pull again - -``` - -Again, you ran into a merge conflict. You are now ready to solve the conflict yourself! - - -```bash - -``` +7. Try to pull again and solve the merge conflict in your preferred way. \ No newline at end of file diff --git a/beginner/Exercise_7/Exercise_7.ipynb b/beginner/Exercise_7/Exercise_7.ipynb deleted file mode 100644 index 1648f4a..0000000 --- a/beginner/Exercise_7/Exercise_7.ipynb +++ /dev/null @@ -1,360 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "normal-chicago", - "metadata": {}, - "source": [ - "## Exercise 7\n", - "\n", - "## Objective\n", - "* Access code from a Git web interface\n", - "* Push code changes to a Git web interface\n", - "* Examine the code repository on a Git web interface\n", - "\n", - "## Helper Functions\n", - "The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with.\n", - "\n", - "For this exercise, we will use the following functions from this file:\n", - " * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work.\n", - " * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely.\n", - "\n", - "## Remarks\n", - "_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._\n", - "\n", - "### Initialization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "alone-lunch", - "metadata": {}, - "outputs": [], - "source": [ - "# check current directory with \"pwd\"\n", - "\n", - "# in case you are in the wrong directory, navigate to Exercise_7 using \"cd\"\n" - ] - }, - { - "cell_type": "markdown", - "id": "7474b65f", - "metadata": {}, - "source": [ - "**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "deluxe-transaction", - "metadata": {}, - "outputs": [], - "source": [ - "# source the helpers.sh file to be able to use its functions\n", - "source ../helpers.sh\n", - "# init exercise\n", - "init_exercise" - ] - }, - { - "cell_type": "markdown", - "id": "applied-wings", - "metadata": {}, - "source": [ - "***\n", - "### Optional: clear notebook and restart\n", - "**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "prompt-inspector", - "metadata": {}, - "outputs": [], - "source": [ - "## only execute in case of (serious) trouble ##\n", - "## it will delete your entire beginners_git directory ##\n", - "reset" - ] - }, - { - "cell_type": "markdown", - "id": "4afe5a33", - "metadata": {}, - "source": [ - "## Exercise\n", - "\n", - "In this exercise, we will work with a repository hosted on the GitHub website.\n", - "\n", - "First, we'll create a fork of the repository so that you can have your own copy of a C2SM repository to work with. A fork is a complete copy of a repository into your own account, where you have full permission to make any changes you want to your forked repository. To create your fork, open another tab in your browser and navigate here: https://github.com/c2sm/git-example\n", - "\n", - "**Use the web interface to make a fork:**\n", - "\n", - "![Fork.png](../images/Fork.png)" - ] - }, - { - "cell_type": "markdown", - "id": "c92c7dc6", - "metadata": {}, - "source": [ - "### Clone the fork\n", - "\n", - "GitHub will indicate at the top left that this repository has been forked (left arrow).\n", - "\n", - "\n", - "Now copy the forked repository to your local workspace using the link (right arrow, dropdown from `Code`). If you have an SSH key on GitHub that connects your local Git to GitHub, use the SSH link to clone, otherwise use HTTPS.\n", - "\n", - "> **Note about HTTPS**: If you clone the repository with HTTPS, you will not be able to exchange any information with the remote repository without setting up a token (`git push`, `git pull` and `git fetch` will NOT work). Follow the instructions in [Create a user token to use HTTPS for working with remote repositories](../token.ipynb) to do so.\n", - "However, we strongly recommend that you create an SSH key for GitHub if you plan to work with it in the future. It will make things much easier!\n", - "\n", - "![Forked_Repo_view.png](../images/Forked_Repo_view.png)\n", - "\n", - "We don't want the repository in our _git-course_ repository. So make sure you are in the _beginners_git_ directory instead. Use the [Basic Unix Commands](../Unix_Commands.ipynb) we provided to navigate there in case you are in the wrong directory." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9cfec661", - "metadata": {}, - "outputs": [], - "source": [ - "# Navigate into beginners_git repo if not there\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "circular-truck", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git clone \" to download your forked repository\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "exotic-child", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"cd\" to enter the repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "verified-source", - "metadata": {}, - "source": [ - "### Examine the repository\n", - "Let's examine the repository. Does it have any remotes? What branches are in it? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ceramic-music", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git remote -v\", \"git branch -a\", and \"git status\" to examine the repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "academic-tucson", - "metadata": {}, - "source": [ - "You should have noticed that your local repository has a remote called \"origin\" pointing to your fork on GitHub. This is the default behavior when you use `git clone` to copy a repository.\n", - "\n", - "### Add to local repository\n", - "Next, let's create a new branch and add a commit to it." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "textile-pension", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git switch -c \" to make a new branch\n" - ] - }, - { - "cell_type": "markdown", - "id": "overall-lemon", - "metadata": {}, - "source": [ - "Make a change to your local repository.\n", - "Remember to make all changes to the schedules directly in Jupyter Notebooks.\n", - " * Go to the *git-example* folder (It should be in the parent directory of the _git-course_)\n", - " * Open *schedule_day1.txt*\n", - " * Add more information to your schedule, i.e., workshops, talks, poster sessions, etc.\n", - " \n", - "**Don't forget to save your changes before coming back!**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "unlike-gardening", - "metadata": {}, - "outputs": [], - "source": [ - "# add and commit your changes\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "95e8ca71", - "metadata": {}, - "source": [ - "### Send local information to GitHub\n", - "\n", - "Now, let's send our new branch to our GitHub fork." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f32d8fad", - "metadata": {}, - "outputs": [], - "source": [ - "# find out current directory; make sure you are in the beginners_git/git-example directory\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "278234da", - "metadata": {}, - "outputs": [], - "source": [ - "# push your local changes to the remote repository using git push origin \n" - ] - }, - { - "cell_type": "markdown", - "id": "a5c93d5d", - "metadata": {}, - "source": [ - "### Examine the GitHub repository\n", - "\n", - "Go back to GitHub and take a look at your forked repository. \n", - "\n", - "Let's use the web interface to examine the repository. Try the following things there:\n", - "\n", - "1. Find the list of commits and examine the files for a specific commit. \n", - "\n", - "2. Change a file and use the web interface to make a new commit to a new branch and automatically create a pull request.\n", - "\n", - "![Edit_file_PR.png](../images/Edit_file_PR.png)\n", - "\n", - "3. Find the pull request and take a look at it." - ] - }, - { - "cell_type": "markdown", - "id": "technological-yorkshire", - "metadata": {}, - "source": [ - "### Update local repository using git fetch\n", - "\n", - "Now, let's get the commit we made on GitHub into our local repository. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "amino-vacation", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git fetch origin\" to download the new commit from your fork\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "federal-dublin", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git status\" to examine your repository\n" - ] - }, - { - "cell_type": "markdown", - "id": "unique-negative", - "metadata": {}, - "source": [ - "Our new commit has been downloaded into a remote branch, but is not yet available in our local branch. Let's use ```git merge``` to update our local branch." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "charming-syndrome", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git merge / -m ''\" to sync up your local branch with the remote one \n" - ] - }, - { - "cell_type": "markdown", - "id": "starting-boston", - "metadata": {}, - "source": [ - "### Update local repository using git pull\n", - "\n", - "Let's examine the difference between `git fetch` and `git pull`. We just used `git fetch` to get a commit from our remote repository, and then we used `git merge` to merge it into our local branch. \n", - "\n", - "First, go back to the web interface and use it to make a new commit by editing a file in the branch you created earlier.\n", - "\n", - "Next, let's merge that commit into our repository." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "present-influence", - "metadata": {}, - "outputs": [], - "source": [ - "# use \"git pull origin\" to download the new commit from your fork\n" - ] - }, - { - "cell_type": "markdown", - "id": "alternative-motivation", - "metadata": {}, - "source": [ - "Take a look at your local branch. You should see that the commit you made has already been merged into your local branch automatically, because `git pull` does both `git fetch` AND `git merge` automatically." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/Markdowns/Exercise_7.md b/beginner/Exercise_7_web_interface.md similarity index 56% rename from beginner/Markdowns/Exercise_7.md rename to beginner/Exercise_7_web_interface.md index 660873d..2e75d72 100644 --- a/beginner/Markdowns/Exercise_7.md +++ b/beginner/Exercise_7_web_interface.md @@ -1,4 +1,4 @@ -## Exercise 7 +# Exercise 7 ## Objective * Access code from a Git web interface @@ -12,39 +12,14 @@ For this exercise, we will use the following functions from this file: * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work. * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely. -## Remarks -_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._ +## Remarks -### Initialization +> **Note:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word. +> **Note:** Some exercises may require the use of basic Unix commands. If you are unfamiliar with Unix systems, refer to the file [Basic Unix Commands](Unix_Commands.md) for a list of all necessary commands. -```bash -# check current directory with "pwd" - -# in case you are in the wrong directory, navigate to Exercise_7 using "cd" - -``` - -**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.** - - -```bash -# source the helpers.sh file to be able to use its functions -source ../helpers.sh -# init exercise -init_exercise -``` - -*** -### Optional: clear notebook and restart -**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.** - - -```bash -## only execute in case of (serious) trouble ## -## it will delete your entire beginners_git directory ## -reset -``` +If everything is still set up from the last exercise, you can continue with [this exercise](#exercise) directly. +Otherwise, please refer to the [Initialization from Exercise 1](Exercise_1_basic_commands.md#initialization). ## Exercise @@ -54,7 +29,7 @@ First, we'll create a fork of the repository so that you can have your own copy **Use the web interface to make a fork:** -![Fork.png](../images/Fork.png) +![Fork.png](images/Fork.png) ### Clone the fork @@ -63,81 +38,36 @@ GitHub will indicate at the top left that this repository has been forked (left Now copy the forked repository to your local workspace using the link (right arrow, dropdown from `Code`). If you have an SSH key on GitHub that connects your local Git to GitHub, use the SSH link to clone, otherwise use HTTPS. -> **Note about HTTPS**: If you clone the repository with HTTPS, you will not be able to exchange any information with the remote repository without setting up a token (`git push`, `git pull` and `git fetch` will NOT work). Follow the instructions in [Create a user token to use HTTPS for working with remote repositories](../token.ipynb) to do so. +> **Note about HTTPS**: If you clone the repository with HTTPS, you will not be able to exchange any information with the remote repository without setting up a token (`git push`, `git pull` and `git fetch` will NOT work). Follow the instructions in [Create a user token to use HTTPS for working with remote repositories](token.md) to do so. However, we strongly recommend that you create an SSH key for GitHub if you plan to work with it in the future. It will make things much easier! -![Forked_Repo_view.png](../images/Forked_Repo_view.png) - -We don't want the repository in our _git-course_ repository. So make sure you are in the _beginners_git_ directory instead. Use the [Basic Unix Commands](../Unix_Commands.ipynb) we provided to navigate there in case you are in the wrong directory. - +![Forked_Repo_view.png](images/Forked_Repo_view.png) -```bash -# Navigate into beginners_git repo if not there +We don't want the repository in our _git-course_ repository. So make sure you are in the _beginners_git_ directory instead. Use the [Basic Unix Commands](Unix_Commands.md) we provided to navigate there in case you are in the wrong directory. -``` +1. Navigate into beginners_git repo if not there already. +2. Use `git clone ` to download your forked repository. -```bash -# use "git clone " to download your forked repository - -``` - - -```bash -# use "cd" to enter the repository - -``` +3. Navigate into the cloned repository. ### Examine the repository Let's examine the repository. Does it have any remotes? What branches are in it? - -```bash -# use "git remote -v", "git branch -a", and "git status" to examine the repository - -``` +1. Use `git remote -v`, `git branch -a`, and `git status` to examine the repository. You should have noticed that your local repository has a remote called "origin" pointing to your fork on GitHub. This is the default behavior when you use `git clone` to copy a repository. ### Add to local repository Next, let's create a new branch and add a commit to it. - -```bash -# use "git switch -c " to make a new branch - -``` - -Make a change to your local repository. -Remember to make all changes to the schedules directly in Jupyter Notebooks. - * Go to the *git-example* folder (It should be in the parent directory of the _git-course_) - * Open *schedule_day1.txt* - * Add more information to your schedule, i.e., workshops, talks, poster sessions, etc. - -**Don't forget to save your changes before coming back!** - - -```bash -# add and commit your changes - - -``` +1. Use `git switch -c ` to create a new branch. +2. Make a change in *schedule_day1.txt* and commit the change to your new branch. ### Send local information to GitHub Now, let's send our new branch to our GitHub fork. - - -```bash -# find out current directory; make sure you are in the beginners_git/git-example directory - -``` - - -```bash -# push your local changes to the remote repository using git push origin - -``` +1. Push your local changes to the remote repository using `git push origin ` ### Examine the GitHub repository @@ -149,7 +79,7 @@ Let's use the web interface to examine the repository. Try the following things 2. Change a file and use the web interface to make a new commit to a new branch and automatically create a pull request. -![Edit_file_PR.png](../images/Edit_file_PR.png) +![Edit_file_PR.png](images/Edit_file_PR.png) 3. Find the pull request and take a look at it. @@ -157,27 +87,15 @@ Let's use the web interface to examine the repository. Try the following things Now, let's get the commit we made on GitHub into our local repository. +1. Use `git fetch origin` to download the new commit from your fork. +2. Check the status of your Git repository. -```bash -# use "git fetch origin" to download the new commit from your fork +Our new commit has been downloaded into a remote branch, but is not yet available in our local branch. -``` +3. Use `git merge / -m ''` to sync up your local branch with the remote one. -```bash -# use "git status" to examine your repository - -``` - -Our new commit has been downloaded into a remote branch, but is not yet available in our local branch. Let's use ```git merge``` to update our local branch. - - -```bash -# use "git merge / -m ''" to sync up your local branch with the remote one - -``` - -### Update local repository using git pull +### Update local repository using `git pull` Let's examine the difference between `git fetch` and `git pull`. We just used `git fetch` to get a commit from our remote repository, and then we used `git merge` to merge it into our local branch. @@ -185,10 +103,5 @@ First, go back to the web interface and use it to make a new commit by editing a Next, let's merge that commit into our repository. - -```bash -# use "git pull origin" to download the new commit from your fork - -``` - -Take a look at your local branch. You should see that the commit you made has already been merged into your local branch automatically, because `git pull` does both `git fetch` AND `git merge` automatically. +1. Use `git pull origin` to download the new commit from your fork. +2. Take a look at your local branch. You should see that the commit you made has already been merged into your local branch automatically, because `git pull` does both `git fetch` AND `git merge` automatically. \ No newline at end of file diff --git a/beginner/Markdowns/Exercise_4.md b/beginner/Markdowns/Exercise_4.md deleted file mode 100644 index 77206ad..0000000 --- a/beginner/Markdowns/Exercise_4.md +++ /dev/null @@ -1,321 +0,0 @@ -## Exercise 4 - -## Objective - * Practice the typical Git workflow - * Understand the function of a *.gitignore* file, and learn the steps involved in creating and configuring it within a Git repository. - -## Structure - -In this exercise, we won't be learning any new Git commands. Rather, we will review all the commands and workflows we learned in the previous exercises. We will do this by working on the *conference_schedule.txt* document and simulating a possible workflow. Since this is a review, there will be less explanation for that part of this exercise. - -In addition to that, we will explore a crucial aspect of Git: the *.gitignore* file. We'll learn how to create and configure this file to manage the files that Git should ignore, enhancing our typical workflow. - - - -## Helper Functions -The following helper functions in the file *helpers.sh* are written by C2SM and are **NOT** **part of Git**. They will set up simple repositories for you that have a short Git history, so that you have something to work with. - -For this exercise, we will use the following functions from this file: - * `init_exercise`: This will create the *beginners_git* directory in the parent directory of the *git-course* directory. It will also delete any old version of the *beginners_git* directory, so don't use the *beginners_git* directory to save any work. - * `reset`: This will delete the *beginners_git* directory and allows you a clean restart of the exercise in case you messed it up completely. - * `init_repo_empty_schedule`: This will create the directory *conference_planning* and a file *conference_schedule.txt* with an empty schedule. - -## Remarks -_**Reminder:** Any text enclosed in `<>` denotes a placeholder to be replaced with a specific string appropriate to your context, i.e. delete `<>` and replace it with the appropriate word._ - -_**Reminder:** Always run `git commit` and `git merge` with a git message `-m `. Otherwise Git may try to open the Git editor, which does not work on jupyter notebook and will break your current session._ - -### Initialization - - -```bash -# check current directory with "pwd" - -# in case you are in the wrong directory, navigate to Exercise_4 using "cd" - -``` - -**To initialize the exercise properly, run this code at the very beginning. Check the Helper Functions section above for more explanation.** - - -```bash -# source the helpers.sh file to be able to use its functions -source ../helpers.sh -# init exercise -init_exercise -``` - -*** -### Optional: clear notebook and restart -**In case you messed up your notebook completely, execute** ***reset*** **in the following cell. Check the Helper Functions section above for more explanation.** - - -```bash -## only execute in case of (serious) trouble ## -## it will delete your entire beginners_git directory ## -reset -``` - -*** -## Exercise - -### Practice typical Git workflow - -First, we will set up a simple Git repository for you using one of the helper functions: - - -```bash -# this line will create the directory `conference_planning` and the empty schedule `conference_schedule.txt` in it -init_repo_empty_schedule -``` - - -```bash -# init Git repository - -``` - - -```bash -# execute "ls -a" to also see the hidden git folder - -``` - -### Understanding *.gitignore* - -The *.gitignore* file is an essential and commonly used feature in Git. It specifies intentionally untracked files that Git should ignore. It's particularly useful for excluding files generated during execution or build processes—like log files, compiled code, or local configuration files—that don't need to be shared within the repository. Creating a *.gitignore* file and listing the file patterns to exclude achieves this. - -**Typical Ingredients of *.gitignore*:** - -Once your *.gitignore* is created, you can specify: - -- **Patterns**: Direct patterns such as *my_file_to_ignore.txt* to exclude specific files or *my_directory_to_ignore/* to exclude specific directories. For example, *.ipynb_checkpoints/* is often added to the *.gitignore* when working with Jupyter Notebooks to ignore checkpoint folders created during development. -- **Wildcards**: Broad patterns like `*.log` to exclude all log files created across the project. -- **Exceptions**: If you've used a wildcard but want to track specific files, precede the exception with `!`. For instance, *!important_log.log* ensures this file is tracked despite the `*.log` exclusion. - -Remember, the *.gitignore* file should be committed into your repository, so it is shared with other developers, ensuring that everyone working on the project is ignoring the same files. - -**Practical Application:** - -Now that you have seen and understood the concept of the *.gitignore* file, you can proceed with your exercises. At a certain point, after you run `git status`, you might notice a file named *.ipynb_checkpoints*. This is created by Jupyter Notebooks to save checkpoint files and it's exactly the type of content we aim to exclude from our Git repository, as it is specific to your local Jupyter Notebook environment. It thus presents a perfect opportunity to apply what you've just learned. Follow these steps to create a *.gitignore* and specify the patterns. Remember to add and commit your *.gitignore* after creating it. - - - - -```bash -# Create `.gitignore` and add the `.ipynb_checkpoints pattern` (Note: make sure you are in the conference_planning directory when running the following command) -echo ".ipynb_checkpoints/" >> .gitignore - -``` - - -```bash -# Add and commit your .gitignore - - -``` - -### Go on with your Exercise - -Add events to the schedule. - -Remember to make any changes to the schedule directly in Jupyter Notebooks: - * Go to folder *beginners_git/conference_planning* - * Open *conference_schedule.txt* - * Change file - -**Don't forget to save your modifications before coming back!** - -Please use this way of editing files throughout the exercise. - -- Add a talk, coffee break, workshop - - -```bash -# commit your changes - - -``` - -The workshop has been canceled and we will have a poster session instead. - -Adjust your document accordingly. - - -```bash -# commit the adapted "conference_schedule.txt" - - -``` - -We continue to plan. Add these three events to *conference_schedule.txt*: - * Lunch break - * Another talk - * Second poster session - - -```bash -# commit your changes - - -``` - -Check if all of your changes are really tracked by Git. - - - -```bash -# check Git status - -# check Git log - -``` - -If you don't have any untracked changes in your repository, proceed to the next part of this exercise. - - - -**It is late at night and your concentration is not very high...** - -By accident you delete all of your existing files... - - -```bash -# CAUTION: executing this panel deletes all files in the current directory -rm * -``` - -Thanks to Git we can easily restore files, even if they are deleted. - - -```bash -# check Git status - -``` - - -```bash -# restore deleted files - -``` - -As a next step, create a new branch and edit the schedule there, since we are not sure yet if Professor X will accept the talk in the morning. - -**Always make sure to reload your file before changing it** - * Change the talk to a workshop - - -```bash -# create new branch and adjust the schedule - -``` - - -```bash -# commit changes - - -``` - -Switch back to branch *main* and create another branch on top of it. -We want to plan an evening activity but are not sure what it will be. Therefore, we create two branches with different activities. - - -```bash -# switch to main - -# create new branch and add an evening activity - -``` - -Add an evening activity and commit the changes. Don't forget to reload your file before changing! - - -```bash -# commit changes - - -``` - -Switch to branch *main* and create another branch on top of it, to add an alternative evening activity. - - -```bash -# switch to main branch - -# create new branch and add another evening activity - -``` - - -```bash -# commit changes - - -``` - -It's time to get an overview of what we just did. -Our repository has currently 4 branches (names may be different for your case): - * *main* (base version of all subsequent branches) - * *alternative_talk* (workshop instead of talk) - * *evening_activity* (First planned activity) - * *evening_activity_alternative* (Alternative activity) - -Ensure your repository contains the same amount of different branches. - - -```bash -# display all branches of the Git repository - -``` - -The talk in the morning has not been accepted. -Therefore merge the branch *alternative_talk* into *main*. - -**Remark:** Make sure you are in the *main* branch before starting the merge, because Git always merges a branch **into** your current branch. - - - -```bash -# merge schedule branch into the main branch - - -``` - - -```bash -# follow good practice and delete the merged branch - -``` - -The last step of the planning is to choose one of the two evening activities. -Decide which one you prefer. - -Merge the corresponding branch into *main*. - -**Don't forget to add a commit message!** - - -```bash -# merge your preferred evening activity into main - -``` - - -```bash -# delete merged branch - -``` - -There is one unused branch left in our repository. -We want to keep the repository clean and nice. So please delete the unmerged branch as well. - -**Remark:** Since we did not merge the remaining branch, it has to be done differently before. But don't worry, Git will tell you what to do. - - -```bash -# delete unused branch - -``` - -**Congrats, you already know the most essential Git commands for the local use of Git.** diff --git a/beginner/README.md b/beginner/README.md index eda44a6..d688d42 100644 --- a/beginner/README.md +++ b/beginner/README.md @@ -2,10 +2,6 @@ This folder contains the exercises for the C2SM Git Workshop "Git for Beginners". Feel free to download the material to practice and enhance your Git skills. -The corresponding [slides of this course](https://c2sm.github.io/events/git_courses/) can be found on our landing page +The corresponding slides of this course can be found on our [C2SM User Landing Page](https://c2sm.github.io/events/git_courses/). -A Markdown version of the .ipynb files for each exercise is located in the [Markdowns folder](Markdowns). - -We recommend that you use the convenient way of doing the exercises with Jupyter Notebook itself. - -See the [Getting Started section](https://github.com/C2SM/git-course/#getting-started) for installation instructions of Git and Python. +Please refer to the [Getting Started section](https://github.com/C2SM/git-course/#getting-started) for installation instructions of Git and Python. diff --git a/beginner/Unix_Commands.ipynb b/beginner/Unix_Commands.ipynb deleted file mode 100644 index 3d57560..0000000 --- a/beginner/Unix_Commands.ipynb +++ /dev/null @@ -1,44 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "brutal-anger", - "metadata": {}, - "source": [ - "# Basic Unix Commands\n", - "\n", - "In this Git course some very basic Unix commands will be used.\n", - "This document describes **ALL** commands needed below:\n", - "\n", - " * `ls`: list all files/folders in current directory\n", - " \n", - " * `cd`: change directory, e.g. `cd test` will go to folder 'test'. To go one directory up, type `cd ..` \n", - " \n", - " * `cat`: concatenate files, in our case we only use it to display the content of text file, e.g. `cat my_file.txt` prints the content of *my_file.txt* to the terminal.\n", - " \n", - " * `source`: run script in the current shell, this means that all variables and functions defined in that file will be available in the current shell\n", - " \n", - " * `echo`: display a line of text\n", - " \n", - " * `>`: redirect ouput to file/device after `>`, overwrites already existing file\n", - " * `>>`: redirect output to file/device after `>>`, appends and does not delete already existing file. \n", - " * `mkdir`: create directory/folder, e.g. `mkdir test` will create directory 'test' " - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/Unix_Commands.md b/beginner/Unix_Commands.md new file mode 100644 index 0000000..d982c23 --- /dev/null +++ b/beginner/Unix_Commands.md @@ -0,0 +1,18 @@ +# Basic Unix Commands + +In this Git course some very basic Unix commands will be used. +This document describes **ALL** commands needed below: + + * `ls`: list all files/folders in current directory + + * `cd`: change directory, e.g. `cd test` will go to folder 'test'. To go one directory up, type `cd ..` + + * `cat`: concatenate files, in our case we only use it to display the content of text file, e.g. `cat my_file.txt` prints the content of *my_file.txt* to the terminal. + + * `source`: run script in the current shell, this means that all variables and functions defined in that file will be available in the current shell + + * `echo`: display a line of text + + * `>`: redirect ouput to file/device after `>`, overwrites already existing file + * `>>`: redirect output to file/device after `>>`, appends and does not delete already existing file. + * `mkdir`: create directory/folder, e.g. `mkdir test` will create directory 'test' diff --git a/beginner/check_for_bash_kernel.ipynb b/beginner/check_for_bash_kernel.ipynb deleted file mode 100644 index 7ee625a..0000000 --- a/beginner/check_for_bash_kernel.ipynb +++ /dev/null @@ -1,107 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "1f440047-22b4-48cd-927b-e1514cbd6aa7", - "metadata": {}, - "source": [ - "### Search for bash Kernel installation" - ] - }, - { - "cell_type": "markdown", - "id": "43c14020-abe2-4011-ab50-75c8c351e8ed", - "metadata": {}, - "source": [ - "For the Git course, we will be using a special notebook that allows us to write and run commands just like we would in the computer's terminal. To make this possible, we use a special Juypter kernel (bash-kernel) in our Jupyter notebook. Think of it as a plugin that helps your notebook understand and execute terminal commands. We need to make sure that this bash kernel is set up before we start the course. To do this, first run the cell below and follow the steps based on the output of the cell below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3d2f9c9f-ea47-41c4-bf48-a70c5068dd51", - "metadata": {}, - "outputs": [], - "source": [ - "# import sys\n", - "import sys\n", - "\n", - "# Check if the 'bash_kernel' is installed\n", - "try:\n", - " import bash_kernel\n", - " print(\"Bash kernel is installed.\")\n", - "except ImportError:\n", - " print(\"Bash kernel is not installed.\")" - ] - }, - { - "cell_type": "markdown", - "id": "78b165fd-684b-4596-9be6-b8897aa96d58", - "metadata": {}, - "source": [ - "### If the above cell returned: ``Bash kernel is not installed.``\n", - "\n", - "This means that your bash kernel is not yet installed and you need to install it yourself.\n", - "\n", - "* To do so, open a terminal and run the following command:\n", - "\n", - " ```bash\n", - " python -m bash_kernel.install\n", - " ```\n", - "* After that, restart this Notebook and run the above cell again to verify that your installation was successful.\n", - "* Continue with instructions below \"If the above cell returned: Bash kernel is installed\" to select the bash kernel.\n", - " \n" - ] - }, - { - "cell_type": "markdown", - "id": "4a682da3-e797-460a-82f6-954ebe3c7e27", - "metadata": { - "jp-MarkdownHeadingCollapsed": true - }, - "source": [ - "### If the above cell returned: ``Bash kernel is installed.``\n", - "\n", - "Perfect! The kernel is already installed, now we only need to properly select it.\n", - "\n", - "* Click on the kernel selection in the top right of your Jupyter Notebook:\n", - "\n", - "
\n", - " \n", - "
\n", - "\n", - "* Select the Bash kernel:\n", - "\n", - "
\n", - " \n", - "
\n", - "\n", - "\n", - "\n", - "\n", - "***Now you're all set to run Bash commands in your notebook!***\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.6" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/convert_to_markdown b/beginner/convert_to_markdown deleted file mode 100755 index 3187cef..0000000 --- a/beginner/convert_to_markdown +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -python3 -m venv venv - -. venv/bin/activate - -pip install nbconvert - -rm Markdowns/* - -for file in $(ls Exercise_*/*.ipynb); do - jupyter nbconvert --output-dir Markdowns --to markdown $file -done - diff --git a/beginner/helpers.sh b/beginner/helpers.sh index 0932dda..aa69a1a 100755 --- a/beginner/helpers.sh +++ b/beginner/helpers.sh @@ -7,15 +7,16 @@ else fi reset () { - echo "Go back to $dir_at_startup and restore clean working directory" + echo "Going back to $dir_at_startup and restore clean working directory" init_exercise &> /dev/null echo "Here we go again!" + pwd } # determine main or master for default branch name get_default_branch_name() { # Attempt to identify the default branch by querying the remote repository - default_branch=$(git remote show origin | grep 'HEAD branch' | cut -d' ' -f5) + default_branch=$(git symbolic-ref refs/heads/HEAD | sed 's@^refs/heads/@@') # Check if the default branch was found; if not, check local references for main, i.e., master branch if [ -z "$default_branch" ]; then @@ -33,16 +34,13 @@ get_default_branch_name() { } init_exercise () { - # Save the name of the current directory - current_dir_name=$(basename "$(pwd)") - cd $dir_at_startup mkdir -p ../../beginners_git rm -rf ../../beginners_git mkdir -p ../../beginners_git cd ../../beginners_git echo -e "Working directory prepared." - echo -e "\033[31m\033[1mYou've been moved to the 'beginners_git' directory. This is where you'll start your ${current_dir_name}.\033[0m" + echo -e "\033[31m\033[1mYou've been moved to the 'beginners_git' directory. This is where you start your exercise.\033[0m" } @@ -51,26 +49,33 @@ init_repo_empty_schedule () { mkdir -p ../../beginners_git/conference_planning cd ../../beginners_git/conference_planning cp ../../git-course/beginner/examples/schedule_day1.txt conference_schedule.txt + echo -e "Working directory prepared." + echo -e "\033[31m\033[1mYou've been moved to the 'conference_planning' directory within the 'beginners_git' directory. This is where you start your exercise.\033[0m" } init_simple_repo () { cd $dir_at_startup - mkdir -p ../../beginners_git/conference_planning + rm -rf ../../beginners_git/conference_planning + mkdir ../../beginners_git/conference_planning cd ../../beginners_git/conference_planning git init - echo ".ipynb_checkpoints" >> .gitignore + + # Dynamically get the default branch name and switch to it + default_branch=$(git symbolic-ref --short HEAD 2>/dev/null) + git checkout "$default_branch" + cp ../../git-course/beginner/examples/schedule_day1.txt . cp ../../git-course/beginner/examples/schedule_day2.txt . git add schedule_day1.txt .gitignore && git commit -m "Add schedule_day1" git add schedule_day2.txt && git commit -m "Add schedule_day2" - 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 + printf "/program/\na\n09:00-11:00: Poster session\n.\nw\nq\n" | ed -s schedule_day1.txt > /dev/null + printf "/program/\na\n09:00-11:00: Poster session\n.\nw\nq\n" | ed -s schedule_day2.txt > /dev/null git add * && git commit -m "Add poster sessions in the morning" - 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 + printf "/session/\na\n11:00-11:15: Coffee break\n.\nw\nq\n" | ed -s schedule_day1.txt > /dev/null + printf "/session/\na\n11:00-11:15: Coffee break\n.\nw\nq\n" | ed -s schedule_day2.txt > /dev/null git add * && git commit -m "Add coffee break" echo "" @@ -82,6 +87,8 @@ init_simple_repo () { echo "Your schedules:" echo"" ls + + echo -e "\033[31m\033[1mYou've been moved to the 'conference_planning' directory within the 'beginners_git' directory. This is where you start your exercise.\033[0m" } init_simple_repo_remote () { @@ -90,32 +97,23 @@ init_simple_repo_remote () { git clone conference_planning conference_planning_remote cd conference_planning_remote git checkout -b "updated_schedules" - ed -s schedule_day1.txt <<< $'/break/\na\n11:15-12:15: Talk professor A.\n.\nw\nq' > /dev/null - ed -s schedule_day2.txt <<< $'/break/\na\n11:15-12:15: Talk professor B.\n.\nw\nq' > /dev/null + printf "/break/\na\n11:15-12:15: Talk professor A.\n.\nw\nq\n" | ed -s schedule_day1.txt > /dev/null + printf "/break/\na\n11:15-12:15: Talk professor B.\n.\nw\nq\n" | ed -s schedule_day2.txt > /dev/null git add * && git commit -m "update schedules" - # Dynamically get the default branch name (main or master, based on the version of git) + # Dynamically get the default branch name and switch to it default_branch=$(get_default_branch_name) - - # Switch to the dynamically determined default branch git checkout "$default_branch" cd ../conference_planning - echo"" - echo -e "\033[31m\033[1mYou've been automatically moved to the 'conference_planning' directory, where the 'Conference Planning' repository is ready for you to go on with your exercise.\033[0m" - - echo"" - echo "Your schedules:" - echo"" - ls } init_repo () { init_simple_repo &> /dev/null - ed -s schedule_day1.txt <<< $'/break/\na\n11:15-12:15: Workshop ice crystal formation\n.\nw\nq' > /dev/null - ed -s schedule_day2.txt <<< $'/break/\na\n11:15-12:15: Workshop secondary ice\n.\nw\nq' > /dev/null + printf "/break/\na\n11:15-12:15: Workshop ice crystal formation\n.\nw\nq\n" | ed -s schedule_day1.txt > /dev/null + printf "/break/\na\n11:15-12:15: Workshop secondary ice\n.\nw\nq\n" | ed -s schedule_day2.txt > /dev/null git add * && git commit -m "Add workshops" sed 's/Poster session/Talk professor C./g' schedule_day1.txt > schedule_day1_tmp.txt @@ -135,26 +133,33 @@ init_repo () { echo "Your schedules:" echo"" ls + + echo -e "\033[31m\033[1mYou've been moved to the 'conference_planning' directory within the 'beginners_git' directory. This is where you start your exercise.\033[0m" } init_repo_remote () { cd $dir_at_startup - mkdir -p ../../beginners_git/conference_planning + rm -rf ../../beginners_git/conference_planning + mkdir ../../beginners_git/conference_planning cd ../../beginners_git/conference_planning git init - echo ".ipynb_checkpoints" >> .gitignore + + # Dynamically get the default branch name and switch to it + default_branch=$(git symbolic-ref --short HEAD 2>/dev/null) + git checkout "$default_branch" + cp ../../git-course/beginner/examples/schedule_day1.txt . git add schedule_day1.txt .gitignore && git commit -m "Add schedule_day1" # Edit schedule_day1.txt - ed -s schedule_day1.txt <<< $'/program/\na\n09:00-11:00: Poster session\n.\nw\nq' > /dev/null + printf "/program/\na\n09:00-11:00: Poster session\n.\nw\nq\n" | ed -s schedule_day1.txt > /dev/null git add * && git commit -m "Add poster sessions in the morning" - ed -s schedule_day1.txt <<< $'/session/\na\n11:00-11:15: Coffee break\n.\nw\nq' > /dev/null + printf "/session/\na\n11:00-11:15: Coffee break\n.\nw\nq\n" | ed -s schedule_day1.txt > /dev/null git add * && git commit -m "Add coffee breaks" - ed -s schedule_day1.txt <<< $'/break/\na\n11:15-12:15: Talk professor A.\n12:15-13:30: Lunch\n13:30-15:00: Workshop\n15:00-16:00: Talk professor B.\n.\nw\nq' > /dev/null + printf "/break/\na\n11:15-12:15: Talk professor A.\n12:15-13:30: Lunch\n13:30-15:00: Workshop\n15:00-16:00: Talk professor B.\n.\nw\nq\n" | ed -s schedule_day1.txt > /dev/null git add * && git commit -m "Add rest of daily program" cd .. @@ -181,13 +186,12 @@ init_repo_remote () { cd conference_planning - echo"" - echo -e "\033[31m\033[1mYou've been automatically moved to the 'conference_planning' directory, where the 'Conference Planning' repository is ready for you to go on with your exercise.\033[0m" - echo"" echo "Your schedules:" echo"" ls + + echo -e "\033[31m\033[1mYou've been moved to the 'conference_planning' directory within the 'beginners_git' directory. This is where you start your exercise.\033[0m" } commit_to_remote_by_third_party() { @@ -215,4 +219,4 @@ commit_to_remote_by_third_party() { rm -rf conference_planning_remote_tmp cd conference_planning -} +} \ No newline at end of file diff --git a/beginner/token.ipynb b/beginner/token.ipynb deleted file mode 100644 index 6759fca..0000000 --- a/beginner/token.ipynb +++ /dev/null @@ -1,46 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "normal-chicago", - "metadata": {}, - "source": [ - "## Create a user token to use HTTPS for working with remote repositories\n", - "GitHub only allows authorized users to push (and pull) to remote repositories.\n", - "If you do not have an SSH key set up, you need to create a GitHub user token.\n", - "\n", - "Please follow the description for [Creating a personal access token (classic)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-personal-access-token-classic) provided by GitHub.\n", - "\n", - "Once you have a token, you can enter it instead of your password when performing Git operations over HTTPS.\n", - "\n", - "**Please save the token somewhere, GitHub will only show it to you once.**\n", - "\n", - "If you use the token when executing the `git push` command, you may get a popup window saying something like _'git-credential-osxkeychain wants to use your confidential information stored in “github.com” in your keychain'_, click `Deny` and proceed to enter your GitHub username.\n", - "\n", - "```\n", - "git push origin \n", - "Username: your_username\n", - "Password: your_token\n", - "```\n", - "\n", - "\n", - "> **Note about SSH**: With an SSH key, you don't need to create a user token but can push directly, as GitHub already has your information. We highly recommend you to set up an SSH key!" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Bash", - "language": "bash", - "name": "bash" - }, - "language_info": { - "codemirror_mode": "shell", - "file_extension": ".sh", - "mimetype": "text/x-sh", - "name": "bash" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/beginner/token.md b/beginner/token.md new file mode 100644 index 0000000..767d90e --- /dev/null +++ b/beginner/token.md @@ -0,0 +1,20 @@ +## Create a user token to use HTTPS for working with remote repositories +GitHub only allows authorized users to push (and pull) to remote repositories. +If you do not have an SSH key set up, you need to create a GitHub user token. + +Please follow the description for [Creating a personal access token (classic)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-personal-access-token-classic) provided by GitHub. + +Once you have a token, you can enter it instead of your password when performing Git operations over HTTPS. + +**Please save the token somewhere, GitHub will only show it to you once.** + +If you use the token when executing the `git push` command, you may get a popup window saying something like _'git-credential-osxkeychain wants to use your confidential information stored in “github.com” in your keychain'_, click `Deny` and proceed to enter your GitHub username. + +``` +git push origin +Username: your_username +Password: your_token +``` + + +> **Note about SSH**: With an SSH key, you don't need to create a user token but can push directly, as GitHub already has your information. We highly recommend you to set up an SSH key! diff --git a/check_requirements_advanced.sh b/check_requirements.sh similarity index 71% rename from check_requirements_advanced.sh rename to check_requirements.sh index 02dd64a..b0421e3 100755 --- a/check_requirements_advanced.sh +++ b/check_requirements.sh @@ -1,11 +1,19 @@ #!/bin/bash +# Define the log file +LOG_FILE="check_requirements.log" + +# Redirect all output to both the terminal and the log file +exec > >(tee -a "$LOG_FILE") 2>&1 + # Check if git is installed if command -v git >/dev/null 2>&1; then echo "Git is installed." # Check git version git_version=$(git --version | awk '{print $3}') - if [[ $(echo "$git_version 2.28" | awk '{print ($1 >= $2)}') -ne 1 ]]; then + major_version=$(echo "$git_version" | cut -d. -f1) + minor_version=$(echo "$git_version" | cut -d. -f2) + if [[ "$major_version" -lt 2 || ( "$major_version" -eq 2 && "$minor_version" -lt 28 ) ]]; then echo "Git version is less than 2.28. Please update Git." else echo "Git version is 2.28 or higher."