Skip to content
Binary file added assets/images/UseSSH_notHTTPS.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
182 changes: 182 additions & 0 deletions lab_instructions_part0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
# Collaborative Git Workflows: SSH Key Generation for GitHub

An SSH key pair consists of a private key and a public key. The private key
should be kept secure in your local machine, while the public key will be
added to your GitHub account to allow for secure authentication.

Summary of key points:

* SSH replaces passwords
* GitHub trusts your machine, not your authentication session
* You can have multiple SSH keys for different purposes (e.g.,
one for authentication and another for signing commits). In this setup, we
use one SSH key pair for both authentication and signing commits to keep
it simple.
* You can have multiple SSH key pairs for different machines, e.g., one
for your personal laptop and another for your work laptop. This way, if
one of your machines gets compromised, you can easily revoke the
corresponding SSH key from your GitHub account without affecting the other
machine that has not been compromised.

***Note:** Ensure you are using the terminal for all Git operations in this
lab, not a graphical Git client like the built-in Visual Studio Code Git
support or GitHub Desktop.*

## Install OpenSSH Client (if not already installed)

### Check if already installed

`ssh -V`

If `ssh -V` returns a version number, you already have OpenSSH installed. If it returns an error, you will need to install it.

<img src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/windows11/windows11-original.svg" width="40" />

Installing OpenSSH in Windows:

### Install the client (not the server)

```bash
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
```

<img src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/linux/linux-original.svg" width="40" /> <img src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/apple/apple-original.svg" width="40"/>

Installing OpenSSH Client in Linux/Mac is usually unnecessary as it is typically pre-installed. However, if you need to install it, you can use the following commands:

* Execute:

```bash
sudo apt update
sudo apt install openssh-client
```

Verify installation:

```bash
ssh -V
```

## Step 1: Open Terminal (Git Bash on Windows or Default Terminal on Linux/Mac)

Execute the following command to generate a new SSH key pair.

```bash
ssh-keygen -t ed25519 -C "<place your comment here>" -f ~/.ssh/id_ed25519_auth_and_sign
````

* `-t ed25519` specifies the type of key to create, which is [https://en.wikipedia.org/wiki/EdDSA](https://en.wikipedia.org/wiki/EdDSA). This is a modern and secure choice for SSH keys.

* The comment can contain the name of the machine. That will help you identify
which key was used and where it was used from, e.g., a key for your personal
laptop and another key for your work laptop in future.

* `-f` specifies the file name of the private key as well as the folder where it
will be saved. The public key will be saved with the same name but with a
`.pub` extension. For example, in this case, the private key will be saved as `~/.ssh/id_ed25519_auth_and_sign` and the public key will be saved as `~/.ssh/id_ed25519_auth_and_sign.pub`.

* `~` represents the home directory of the current user. On Windows, this translates to `C:\Users\YourUsername`.

After running the command, you will be prompted to enter a passphrase. You can
leave it empty for no passphrase or enter a secure passphrase for added
security. If you enter a passphrase, you will need to remember it to use the
key. In this case, we leave it empty for simplicity, however,
in a professional setting, it is recommended to use a passphrase for added
security.

## Step 2: Add the PUBLIC (.pub) Key to Your GitHub Account

Log in to your GitHub account, navigate to "Settings" > "SSH and GPG keys" >
"New SSH key". Paste **all the contents** of your public key file
(`~/.ssh/id_ed25519_auth_and_sign.pub`) into the "Key" field and select
"Authentication Key" as the type.

Make sure that you are copy-pasting your public key, and **NOT** the private key.
Your private key (`~/.ssh/id_ed25519_auth_and_sign`) should never be shared with anyone.
The public key is safe to share and is used to authenticate your identity when
connecting to GitHub.

Give it a descriptive title, e.g., `Git authentication for GitHub from
<your_laptop_name>`. That way, if your laptop gets compromised, you can
easily identify which private key was being used for authentication and
revoke it from your GitHub account.

Click "Add SSH key" to save it.

Register the same public key again, but classify it as a signing key. This
way, you can use the same SSH key pair for both authentication and
signing commits. You can also choose to use different SSH key pairs for
authentication and signing if you prefer, but using the same key pair
simplifies the setup.

## Step 3: Add the SSH Key to the Local SSH Agent

First confirm that the SSH agent is running:

```bash
eval "$(ssh-agent -s)"
```

On Windows, if this command fails, ensure that the OpenSSH Authentication Agent service is running via Services.

```bash
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519_auth_and_sign.pub
git config --global commit.gpgsign true
```

Then add the private key to the SSH agent:

```bash
ssh-add ~/.ssh/id_ed25519_auth_and_sign
```

## Step 4: Test the SSH Connection to GitHub

To verify that your SSH key is correctly set up and can authenticate with GitHub, run the following command:

```bash
ssh -T git@github.com
```

You should see a message like this:

```text
Hi <your_github_username>! You've successfully authenticated, but GitHub does not provide shell access.
```

This indicates that your SSH key is correctly configured and you can now use it for Git operations with GitHub.

---

However, if you see a message like this:

```text
Permission denied (publickey).
```

Or any other error message, you can troubleshoot the issue by running:

```bash
ssh -vT git@github.com
```

---

You should now be using SSH for both Git authentication when cloning repositories and for Git signing when committing changes.

![Use SSH not HTTPS](./assets/images/UseSSH_notHTTPS.png)

The cloning command in this case would then be as follows to clone the repository using SSH and store the code in a folder named `Lab-1-Git`:

```bash
git clone git@github.com:course-files/Git.git Lab-1-Git
```

The syntax is:

```bash
git@github.com:<username>/<repository>.git <name-of-repository-in-your-local-machine>
```

This setup enhances the security of your interactions with GitHub while also providing a convenient way to manage your Git operations.
42 changes: 34 additions & 8 deletions lab_instructions_part1.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ All team members should clone the repository to their local machines:
## 3. Create a Project (Member 2)

1. Go to the **Projects** tab in the repository and click on **New Project**.
2. Select the **Iterative development** template and name it "**202604 Business Intelligence Labs**".
2. Select the **Iterative development** template and name it "**[GROUP NAME] Business Intelligence Labs**".
3. Ensure that your team members are added to the project as collaborators with **Admin** rights. This can be done in the project **Settings** > **Manage access**.
4. Create iterations and specify the start and end dates for each iteration. This is available under the project **Settings** > **Iterations**.

Expand All @@ -64,7 +64,7 @@ Have a discussion as a team to determine the specific technical tasks that need
2. Each issue should be assigned to the respective member of the team.
3. Each issue should be assigned the label "**enhancement**".
4. Each issue should be assigned the type "**Feature**".
5. Each issue should be assigned to the "**202604 Business Intelligence Labs**" project.
5. Each issue should be assigned to the "**[GROUP NAME] Business Intelligence Labs**" project.

Example issues for the lab:

Expand All @@ -78,7 +78,7 @@ Example issues for the lab:

## 6. Assigning Issues to Iterations and Managing the Status of Issues

1. Go to the **Projects** tab and open the "**202604 Business Intelligence Labs**" project. Navigate to the **My items** view where you can see all the issues in the backlog.
1. Go to the **Projects** tab and open the "**[GROUP NAME] Business Intelligence Labs**" project. Navigate to the **My items** view where you can see all the issues in the backlog.
2. For each issue, click on the issue title and assign it to the appropriate iteration based on its milestone. Example:
* Issues #1, #2, and #3 are planned for Iteration 1, which corresponds to the **50% Complete Milestone**.
* Issue #4 is planned for Iteration 2, which corresponds to the **75% Complete Milestone**.
Expand Down Expand Up @@ -186,7 +186,7 @@ git push origin feature/lab-number/description
2. Name the PR appropriately, e.g., "*Merge feature/lab-1/update-project-readme into main*" and add a detailed description of the changes made. This description should provide context for the reviewer, explaining the motivation behind the changes and any relevant details that would help them understand the purpose of the PR.
3. Link the PR to the corresponding issue by including `#issue-number` in the PR description. This creates a connection between the changes and the issue it addresses. A common way to include the issue number is to use the text "`Closes #issue-number`" in the PR description, e.g., "`Closes #2`". This not only links the PR to the issue but also automatically closes the issue when the PR is merged.
4. Assign a teammate to perform a **Code Review**. If this was your research/project, then your research supervisor would be the assigned reviewer. The author of the PR should not merge their own PR. This is a critical aspect of team governance and ensures that all changes are reviewed by at least one other team member before being integrated into the main branch.
5. The assignees can be anyone who contributed to the commits in the branch, the label can be "**enhancement**" for a new feature, the projects should be the 202604 Business Intelligence Labs, and the milestone should correspond to the one assigned to the issue that the feature branch addresses.
5. The assignees can be anyone who contributed to the commits in the branch, the label can be "**enhancement**" for a new feature, the project should be the **[GROUP NAME] Business Intelligence Labs**, and the milestone should correspond to the one assigned to the issue that the feature branch addresses.

### Step D: The Code Review

Expand Down Expand Up @@ -241,9 +241,11 @@ Member 4 merges first through the normal PR process. By the time Member 5 attemp

### Resolution process (Member 5)

**IMPORTANT:** The standard practice **before opening any PR** is to update your feature branch with the latest changes from main. This is where conflicts are detected.
#### Option 1

Before opening a PR, Member 5 updates their local feature branch with the latest state of main:
**IMPORTANT:** The standard practice **before opening any PR** is to update your feature branch with the latest changes from main. This is one of the places where conflicts can be detected.

Before opening a PR to merge `feature/lab-number/description` into `main`, Member 5 updates their local feature branch with the latest state of main:

```bash
git checkout feature/lab-number/description
Expand All @@ -258,7 +260,7 @@ CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts then commit the result.
```

Open README.md in your IDE (VS Code). Git marks the conflict zone as follows:
Open the file with the merge conflict (README.md in this case) in your IDE (VS Code). Git marks the conflict zone as follows:

```text
<<<<<<< HEAD
Expand All @@ -272,6 +274,24 @@ The section between **<<<<<<< HEAD** and **=======** is your version

The section between **=======** and **>>>>>>> origin/main** is the version already in main.

---

#### Option 2

Member 5 can proceed to push the changes to their branch and then open the PR without updating their local branch with the changes in main.

To open a PR without updating the branch with changes from main:

```bash
git push origin feature/lab-number/description
```

When they attempt to merge, GitHub will detect the conflict and prevent the merge until the conflict is resolved. The process of resolving the conflict in the web interface in the origin (on [GitHub.com](https://github.com)) is similar to the local resolution process described below, but it may be more cumbersome for complex conflicts with multiple merge conflicts at a time.

**The 'GitHub Flow' recommends not having your branches opened for too long because it increases the chances of you changing the same lines as other team members, which leads to conflicts.**

---

Member 5 must decide what the final file should say. In this case, both attributions are valid — combine them as follows:

```text
Expand All @@ -280,15 +300,21 @@ Project lead: Member 4 (coordination) and Member 5 (governance and audit).

Delete all three conflict markers (<<<<<<<, =======, >>>>>>>) and save the file.

Stage the resolved file and complete the merge:
**If you were using Option 1**, stage the resolved file and complete the merge:

```bash
git add README.md
git commit -m "Resolve merge conflict: consolidate dual attribution in README"
```

**If you were using Option 2**, click the "Resolve conflicts" button in the GitHub web interface, edit the file to resolve the conflict as described above, and then commit the resolution directly in the web interface.

---

Member 5's branch now contains a clean merge commit. Proceed to push and open your PR as normal.

---

**Key principle:** A conflict is not an error — it is Git asking a human to make a decision that a machine cannot. The discipline lies in reading both versions carefully before choosing, not in simply accepting one side and discarding the other.

The quality of the resolution matters as much as the resolution itself. In a professional codebase, a careless conflict resolution that silently discards one team member's valid change is far more dangerous than the conflict itself, precisely because it leaves no trace.
Expand Down