# 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
:::

(creating-the-first-commit=)
## Creating the first commit

[When you created your project](project:#creating-a-project), you automatically created a repository in your project folder, unless you deactivated the field for Git repository creation.

:::{card} Troubleshooting
If Rider errors out about git being not installed, then run the following command in your terminal:

```sh
xcode-select --install
```
:::

In the beginning a repository is empty. Our initial project files will be the first *changeset* – a set of file changes. With this *changeset*, we will create our first *commit*.

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

:::{wpd} commit
:id: Commit_(version_control)
the operation of committing such a changeset to the repository
:::

1. On the left-most side of Rider, there is a tool bar. In the bottom of the toolbar, click the {{AllIcons_expui_toolwindows_vcs}} symbol. The Git Log tab will show up and you will see `No changes committed`.

2. In the middle of the opened window in the bottom, Click `Commit local changes`. On the upper left part of the IDE you will see a `Commit` window with four files activated and marked <span style="color: green;">green</span>. This is the changeset that we will *commit* to the local repository on our hard drive.

   You will see also `unversioned files`, because the IDE has automatically chosen the files that are somewhat crucial for *sharing* the project with others. For example `*.DotSettings.user` file was not included, because it contains personal settings which are irrelevant for others.

1. Each commit is typically documented with a *commit message*.

   In the `Commit Message` below, write `initial`, because these will be our initial files.
   
(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. Click to `Commit`. You should see at least two windows popping up:

   1. `Share Project On GitHub`, we will use this window later.

   2. In the bottom right, a notification window stating

      > ... files committed
      > ...
      > Share Project on GitHub     On GitLab

<!--
1. If you don't know GitHub nor GitLab, I recommend choosing GitHub, which has a more intuitive user experience. In the following I described the steps for GitHub.
-->
1. Click `Share Project on GitHub`.
1. A new window should pop up `Log In to GitHub`. Click `Log In via GitHub` to login on GitHub. You will be forwarded to JetBrains website first, which forwards you to GitHub.

   If you don't have an account, create an account during this step.
   
1. After logging in and authorizing Rider to access your GitHub account, go back to Rider to the `Share Project on GitHub`.

   *Deactivate* `Private` flag, so others see your repository, when you submit your work.
   
   Rest of the info can stay with their default values.
   
   Click `Share`. You should see a notification window stating `Successfully shared project on GitHub.`

:::{figure} ../img/local-and-remote-repository-configuration.png
:name: local-and-remote-repository-configuration
:align: right
:figwidth: 30%
Git window showing the local and remote repository information after setting up the remote repository.
:::

  Now you should see that a remote repository configuration is added to your configuration as shown in {numref}`Figure %s <local-and-remote-repository-configuration>`.

## Checking the forge after push

To see if everything went correctly, you can 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
```

## 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 IDE, 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.


## Checking the forge after push

To see if everything went correctly, you can browse <https://github.com> and search for your project there. Your project should be on `https://github.com/YOUR_USERNAME/YOUR_PROJECT`.

You should see something similar to:

```text
YOUR_USERNAME  initial   ... 1 Commit

.gitignore
CurrencyConverter.csproj
CurrencyConverter.sln
Program.cs
```

## Purpose of automatically tracked files

- `.gitignore` lists the files which should be ignored by git. These are typically intermediate files generated when we build our project. If you peek inside the folder, you will probably see:

  ```text
  bin/
  ...
  ```
 
  `bin` stands for *binary* and contains the compiled program (`*.exe`) and other related files. The compiled program can be generated using `Program.cs` and should not be added to the repository.

  `.gitignore` files is provided by Rider and usually added with your initial commit.

- `*.csproj` and `*.sln` are project and solution files. VS takes care of them when we save our project.
- `Program.cs` is our source code

:::{wpd} source code
a plain text computer program written in a programming language
:::


## 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 IDE
:::{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 improved your currency converter code `Program.cs` so that it supports also Dollar to DKK and added the flowchart image `flowchart.svg`.

1. Click {{AllIcons_expui_vcs_commit}} on the left sidebar. A `Commit window will show up on the left.
1. Select the files `Program.cs` and `flowchart.svg` and write a meaningful message, e.g., `Dollar-DKK conversion support, added visualization` as shown in {numref}`Figure %s <git-staged-changes>`.
1. Click `Commit and Push`. A window with title `Push Commits to ...` will pop up.
1. Click `Push`. You will see a notification about your push.

*Push* means sending a copy of our local changes to the forge.

## 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 saw three unversioned files in {numref}`Figure %s <git-staged-changes>`. These are not important for running our project and you can ignore them by following the steps using the `.gitignore` file:

1. Click the {{AllIcons_expui_nodes_folder}} icon on the sidebar.
1. Open `.gitignore` in the root our project.
1. Append the `.idea` folder as follows:

   ```text
   ...
   /_ReSharper.Caches/
   .idea
   ```
   `.gitignore` contains the names of files or folders which should be ignored by git.
1. Save the file.
1. Go to {{AllIcons_expui_vcs_commit}}. You should see that the three irrelevant files from {numref}`Figure %s <git-staged-changes>` are gone and will never be shown to you, even they exist.
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

We will build a snapshot link using the *commit id* and GitHub's URL.

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

1. Click the {{AllIcons_expui_toolwindows_vcs}} symbol. The Git Log tab will show up.

   If you already [pushed to the forge](project:#sharing-our-repository-on-github), then you should see {numref}`Figure %s <local-and-remote-repository-configuration>` and a list of commit/s as follows: 
   
   :::{image} ../img/a-list-of-commits.png
   :::
1. Right click the commit that corresponds to the project version you want to submit. You will probably choose the latest commit.
1. On the right-click menu click `Copy Revision Number`. This is the commit id.

The snapshot link consists of the commit id and the forge prefix. For example if we break the following snapshot link down:

{#submission-link-format}
```
https://github.com/goekce/CurrencyConverter/tree/aa43207e57b86997c4daf6b55325059acc7bc021
```

:::{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} ../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} ../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).
-->
## Appendix

### Creating and adding a new GitHub repository manually

1. Create an account on <https://github.com> and login.
1. On your [dashboard](https://github.com), click the <span style="color: green;">green</span> `New` button. `Create a new repository` window should come up.
1. Enter `currency-converter` as repository name.
1. Click `Create repository`. You will be forwarded to the page of your repository.
1. There are two ways to connect to the remote repository on GitHub: HTTPS and SSH. Even SSH is the most common method, it requires setting up SSH keys, which may be difficult for you as a beginner. For the sake of simplicity, we will use HTTPS.

   Click `HTTPS` to get the HTTPS address. Copy this address. You can use this address to define a remote manually in the IDE.
 
## Setting up a forge in Rider manually

1. After your changes, click `Commit and Push`. A window titled `Define Remote` will probably pop up. (*did not test this*)
1. Create a repository on the forge. On the `Define Remote` window and paste the repository address to the `URL` field.
1. Click `OK`. You will be back on the `Push Commits` window.
1. Click `Push`. A window `Login In to GitHub` will pop up.
1. Click `Login In via GitHub...`. A web browser window will pop up and forward you to a page on <https://account.jetbrains.com>.
1. Click `Authorize in GitHub`. You will be forwarded to GitHub to authorize the IDE.
1. Click `Authorize JetBrains`. After confirmation you will get a message `Pushed main to new branch origin/main` on the IDE.
