# Organizing code in a repo

Now we will learn how to organize our code on a repository primarily for keeping a diary about our work and sharing it. First we will store them in a local repository and afterwards in a remote one.

:::{wpd} repository
:id: Repository_(version_control)
(in context of version control systems) a data structure that stores metadata for a set of files or directory structure. The main purpose of a repository is to store a set of files, as well as the history of changes made to those files.
:::

:::{wpd} version control
the software engineering practice of controlling, organizing, and tracking different versions in history of computer files; primarily source code text files, but generally any type of file.
:::

## Why do we use repositories?

Most programmers use repositories to organize their software projects, but should you – as a student in this course?

Keeping a history of changes is helpful if we or someone else who also work in the project would like to understand changes in the project which is useful for *collaboration*. Keeping a history helps also to roll changes back if something does not work as intended.

Keeping projects in a repository is also helpful to collaborate and share code. You will use it later to share or submit your projects. You maybe already downloaded something from the code forges [GitHub](https://github.com), [GitLab](https://gitlab.com), or [Codeberg](https://codeberg.org). GitHub is the most popular one and on which most of the open source projects in the world are organized. GitLab is popular among companies, because GitLab is open-source. Codeberg is European and is privacy-focused.

Last but not least, pushing your code to a forge will keep a backup of your project in the cloud.

:::{wpd} forge
:id: forge (software)
a web-based collaborative software platform for developing and sharing software applications
:::

## Installation

Git is the most popular version control software. Before we can use git related functions in the editor, we have to install git using our package manager:

::::{tab-set}
:::{tab-item} Windows
```
winget install git.git
```
:::
:::{tab-item} MacOS
```
brew install git
```
:::
::::

(repository-initialization)=
## Repository initialization && creating the first commit

Go back to your editor.

1. On the activity bar, click the {{source_control}} icon. `Source Control` window will open up.
1. On the `Source Control` window, you should see `Initialize Repository` button. If not, click `reload`.
1. Click `Initialize Repository`. `Changes` window will show up, which should show you the following files:

   1. `main.c`
   1. `main`
   1. `tasks.json`
   1. `launch.json`
   1. `compile_flags.txt`

   You will see `U` beside these files. `U` stands for *untracked*, which means these files are not tracked by the repository.
   
   Typically only *source files* and files for compiling the project are tracked in a repository, so we will only track `main.c`, `tasks.json`, `launch.json`, `compile_flags.txt`, but not the compiled file `main`.

   :::{figure} ../img/git-untracked-added.png
   :name: git-untracked-added
   :align: right
   :figwidth: 40%
   Four added files (`A`) and one untracked (`U`) file on the `Changes` window. `5` on the {{source_control}} icon indicates that there are changes on 5 files.
   :::
1. To add these two files to the repository – or to *track* in other words, hover on the filenames and click the {{add}} symbol on each. You will an `A` on the right of the files, which stands for *added* as depicted in {numref}`Figure %s <git-untracked-added>`.

1. Click the `Message` prompt to write a commit message. When we use repositories we make our changes in *commits*.

   Ideally each commit should be a set of changes that adds one or many describable feature like *improved user name handling* or *added robot program*. The advantage is that the programmer can roll back changes if these features led to problems later. Sometimes people don't want to put so much structuring work and use a repository as a *diary* and commit code at the end of the day, which is not a good practice in a professional environment.

   This is our first commit, so use the message `initial`.

1. Click the {{check}} `Commit` icon. You will see your first commit on the `Graph` window below.

:::{warning}
When you commit your first changeset, you may get an error about that you did not setup [git username](https://docs.github.com/en/get-started/git-basics/setting-your-username-in-git) and [email](https://docs.github.com/en/account-and-profile/how-tos/setting-up-and-managing-your-personal-account-on-github/managing-email-preferences/setting-your-commit-email-address#setting-your-email-address-for-every-repository-on-your-computer). Git attaches a name and email address for each commit to identify the committer.

Setup them using following commands on a terminal. You can choose any name or email. If you use your GitHub username, then the forge will link your commits to your profile.
```sh
git config --global user.name "YOUR NAME"
git config --global user.email "YOUR_EMAIL"
```
:::

:::{wpd} changeset
list of differences between two successive versions in a repository
:::

:::{wpd} commit
the operation of committing such a changeset to the repository
:::

(sharing-our-repository-on-github)=
## Sharing our repository on GitHub

The repository we used is until now local to our computer. Now we will create a copy of the local repository on GitHub.

1. On the `Graph` window, click the {{cloud_upload}} `Publish Branch` icon. A confirmation window will pop up to sign in using GitHub.
1. `Allow`. A new window will pop up with authentication code.
1. `Copy & Continue to GitHub`. A new confirmation window will pop up.
1. `Open`. A browser window will pop up.

   Create (if you don't have an account) and login to GitHub. You will be forwarded to the `Device Activation` page on GitHub.
1. Paste your code. `Authorize Visual Studio Code` should come up.

   If the code is not available anymore, go back to the editor and start from step 1.

1. Click `Authorize Visual-Studio-Code`. You should see `Congratulations` ...
1. You can close the browser.
1. A window will pop up with two options — whether you want to publish privately or publicly. You will use this repository to submit your work, so: select `Publish to GitHub public repository ...`.
1. You will get the notification `Successfully published ...`.

   If you missed the notification, click the {{bell}} (bell) icon in the below right corner of the editor.

## Checking the forge after push

After pushing your code, you should see the notification on the bottom left:

> Successfully published the "YOUR_USERNAME/PROJECT" repository to GitHub.

To see if everything went correctly, Click `Open on GitHub`.

If you cannot find this notification, you can also browse <https://github.com> and search for your project there. If you cannot find it, you can also use the following URL template: 

```text
https://github.com/YOUR_USERNAME/YOUR_PROJECT
```

You should see something similar to:

```text
YOUR_USERNAME  initial   ... 1 Commit

.vscode
compile_flags.txt
main.c
```

## Adding a README on GitHub

When we share work, we should also write some information about what the code is about in the README file.

We could do these steps in our editor, but we will try the web interface to demonstrate the synchronization between the forge and local repository.

1. Go to <https://github.com> and to your project repository.
1. On the repository page on GitHub, click `Add a README`.

1. You can write something along the lines of:

   ```markdown
   # Hello

   An example program for my C programming course.
   ```

   Click `Preview` to see how this text will be rendered.

1. `Commit changes...`. `Commit changes` window will pop up.
1. You can leave the automatic commit message. `Commit changes`. You will be forwarded to your main repository page.

## Synchronizing repositories on the code forge and local computer

1. You can close GitHub.
1. We made changes on GitHub, which are not visible on the repository on our computer.
1. On the editor, if you have a notification about: `Would you like ... to periodically run "git fetch"?`. Click `Yes`, unless you prefer manually pulling the changes. If you don't see the notification, then search for `git.autofetch` in settings and activate it.

   This setting will automatically get the project updates from the forge. This is useful when we collaborate or edit our code on different platforms, e.g., local computer, web-based IDE or on the forge.
   
1. Auto-fetch will automatically download the changes you have done on the forge every 3 minutes. After some time you should see that the blue {{target}} `main` icon will be below the violet {{cloud}} `origin/main` icon. If not, you manually fetch using the {{repo_fetch}} icon.

  The different levels of the {{cloud}} and {{target}} icon means that your repository downloaded the changes from the forge, but they are currently not applied. The application operation is called *pull*.

1. To pull the changes, on the `Graph` window, click {{repo_pull}} `Pull` icon. Now the icons {{target}} and {{cloud}} will be on the same level.


## When should we create additional commits?

After you have a meaningful progress on your project, then you should create a commit. Let us take this website as an example. These course materials are also organized in a repository. When I begin working, a have typically a goal, e.g., I want to write a new section about *Organizing code in a repo* in the file `organizing-code-in-a-repo.md`. In the process of writing this section, then I may also have to modify other already existing files like `first-project.md` and `ide-installation.md`. When I am finished, my changeset will consist of the modifications in `first-project.md` and `ide-installation.md`, and the new file `organizing-code-in-a-repo.md`. Then I would *stage* these three changes and write a commit message like:

> new section: Organizing code in a repo

Finally I would commit and push my changes.

## Adding additional commits in the editor

:::{figure} ../img/git-staged-changes.png
:name: git-staged-changes
:align: right
Two staged files after our initial commit.
:::

Now we will create commits in our editor ourselves. Let us assume you have an initial commit that contains your initial C project. You modified your `main.c` by formatting the code and added the flowchart image `flowchart.svg` that documents your code.

1. On the activity bar, click the {{source_control}} icon. `Source Control` window will open up.
1. Hover over one file that you want to stage before committing, then click the {{add}} symbol. Repeat this for each file you want to stage.

   In our case we want to add `flowchart.svg` and `main.c`.

   After staging, your Changes window should look like {numref}`Figure %s <git-staged-changes>`.
1. Write a descriptive message, e.g.,

   > formatting & flowchart
   
1. Click `Commit` or `Commit & Push`. The latter is under the {{chevron_down}} icon.

## Which files belong to the repository?

Only add source files and project files which are relevant to compile and run your code to the repository. Files *generated from source files usually do not belong to the repository*, e.g., `*.exe`, log files etc. Some reasons are:
- A repository is typically used to track changes in text files, because text files consists of readable lines which can be easily differentiated between commits. 
- We want to keep our repository minimal to avoid complexity. If some files can be easily generated using the source files, we have less amount of files by avoiding generated files.


## `.gitignore` for hiding files that do not belong to the repo

We did not stage one of the files in {numref}`Figure %s <git-staged-changes>` – `main` (`main.exe` on Windows). We should never commit an executable file, so hiding it forever from git changes would be more convenient.

You can ignore it by following the steps using the `.gitignore` file:

1. Click the {{files}} icon on the sidebar.
1. In the root of your project, create a file named `.gitignore` and open it.
1. Add the following line

   ```
   main
   ```
   `.gitignore` contains the names of files or folders which should be ignored by git.
1. Save the file. You will see that the green <span style="color:green">U</span> symbol right to the `main` will vanish and `main` will also be grayed out.

   The graying out helps with focusing on source files instead.

1. Click the {{source_control}} icon. You will see that `main` does not show up anymore.
1. Stage `.gitignore` and commit (and push) your changes.

## Getting the forge link for submissions 

Each commit is like a *snapshot* of your project. In a metaphorical sense, you take a photo of your project in each commit and this photo does not get lost. Each commit receives an individual numerical id which identifies the snapshot. 

You should use a snapshot of your work instead of the latest version when submitting your work. By submitting the snapshot link you can continue working on your project. Moreover it will be a proof that you submitted your work before the deadline and are fair to other students.

### Manually

:::{figure} ../img/git-copy-commit-id.png
:name: git-copy-commit-id
:align: right
Copy commit id option upon right clicking a commit
:::
We will build a snapshot link using the *commit id* and GitHub's URL.

First let us get the *commit id*. The commit id is a unique name for a commit that also describes a snapshot of our project.

1. Click the {{source_control}} icon.
1. Look on the Graph, which lists your commits.
1. Right click the commit that corresponds to the project version you want to submit. You will probably choose the latest commit.
1. Right click the commit and click `Copy Commit ID` as shown in {numref}`Figure %s <git-copy-commit-id>`.

{#submission-link-format}
The snapshot link consists of the commit id and the forge prefix. For example if we break the following snapshot link down:

```
https://github.com/goekce/CurrencyConverter/tree/f60a350130ec8f3633b68e6e65f3504f17a2cda1
```

:::{list-table}
:width: 40%
:header-rows: 1
* - link component
  - description
* - `https://github.com`
  - forge
* - `goekce`
  - **username**
* - `CurrencyConverter`
  - **project**
* - `tree`
  - indicates that you want to view the file and directory structure
* - `aa4307...`
  - **commit id**
:::

You have to fill **username**, **project** and **commit id** with your own data and submit the resulting link.


### Using the web interface

1. Go to your project on <https://github.com>, if you cannot find it it should be under `https://github.com/USER_NAME/PROJECT_NAME`, e.g., <https://github.com/goekce/CurrencyConverter>.
1. Assuming that you want to the get the commit id of the latest commit: Click the latest commit id shown in the following screenshot:

   :::{figure} ../industrial-programming/img/latest-commit.png
   Mouse pointer near the latest commit id on GitHub.
   :::
   
   You will be forwarded to the commit page which details the changeset.
1. Click the top right `Browse files` as shown in the following screenshot:

   :::{figure} ../industrial-programming/img/browse-files-button-github.png
   Mouse pointer on the `Browse files` on GitHub.
   :::

   You will be forwarded to the address that you can use for submission, which should have the pattern shown in the [previous section](#submission-link-format).

:::{spelling}
repos
:::
