Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pages/en/_meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default {
"d3-chart": "Animated charts with D3 🧑‍🎨",
"d3-map": "Animated maps with D3 🗺️",
"web-scraping": "Web scraping 🔍",
"git-and-github": "5. Git & GitHub 🐙",
"ninja-moves": "Ninja moves 🥷",
inspirations: "Inspiring people & content 📚",
"more": "More to come...",
Expand Down
3 changes: 3 additions & 0 deletions pages/en/git-and-github/_meta.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
"git-basics": "How to use Git?",
};
316 changes: 316 additions & 0 deletions pages/en/git-and-github/git-basics.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
---
title: What is Git and how to use it?
description: In this lesson, we learn the basics of using Git.
---

import { Callout } from "nextra/components";
import { NoticeIntro, NoticeEnd } from "../../../components/Notices.jsx";

# What is Git and how to use it?

Programming is hard. You have a lot of code in many files, making it difficult to keep track of everything you're doing. It's even harder if you're collaborating with other people!

This is why [Git](https://git-scm.com/) was released in 2005 and is now used by millions of coders around the world. It's an open source **version control system**. It's the kind of tool that, once you start using it, you wonder how you ever worked without it!

In this project, we will create a simple program to retrieve the current temperature in Montreal and use Git to version it at every step.

Note that I'll show you how to use Git in the terminal. I think it's important to understand how this tool works. But the next lesson will be more visual thanks to GitHub’s interface.

<NoticeIntro />

## Setup

First, you need to install Git. The steps might be different depending on your operating system. Follow [the relevant steps on the Git official website](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).

![Git installation steps.](/assets/git-and-github/git-basics/install.png)

## Initialization

Once Git installed, create a new folder and open it with VS Code.

If you click on `Source Control` in the left sidebar, you'll see that there is no Git repository in this project.

![Message in VS Code saying that there is no Git repository.](/assets/git-and-github/git-basics/no-repo.png)

To initialize a new Git repository, run this command in the terminal: `git init`.

Now, your project is using Git! But there’s nothing in it yet.

![Message in VS Code saying that there is a Git repository.](/assets/git-and-github/git-basics/repo-init.png)

Everything you save with Git will be stored in a hidden `.git` folder in your project.

![A hidden git folder.](/assets/git-and-github/git-basics/git-folder.png)

## New files

Let's create a new file `main.ts` and fetch the latest weather data in Montreal from the [Meteorological Service of Canada API](https://eccc-msc.github.io/open-data/msc-data/obs_station/readme_obs_insitu_swobdatamart_en/).

This API returns data as XML. We log it to the terminal.

```ts showLineNumbers filename="main.ts"
const response = await fetch(
"https://dd.weather.gc.ca/observations/swob-ml/latest/CWTQ-AUTO-minute-swob.xml",
);
const xml = await response.text();

console.log(xml)
```

Now, you can see your new file under `Changes`. Its color also switched to green and there is a `U` next to it, meaning `Untracked`. You can also see a `1` in the left sidebar, next to the `Source Control` button, indicating that one file has been changed.

Git is telling you that it's a new file—it hasn't seen it before and it's not currently being tracked.

![Message in VS Code saying that there is an untracked file.](/assets/git-and-github/git-basics/new-file.png)

Just to make sure the code works, you can run `deno -A main.ts`. You should see the XML data logged in the terminal.

![XML data logged in the terminal.](/assets/git-and-github/git-basics/xml-logged.png)

## Tracking and committing

Git doesn't auto-save your work. You need to tell it when to save your project. To save your changes, you need to **commit** them. Each commit has an ID (generated by Git) and a message you provide.

Committing is a two-step process:
- First, you track the files (new files, deleted files)
- Then, you commit them with a message

Let's do it. To track all files in the project, run this in your terminal: `git add -A`

Then commit with: `git commit -m "Fetching XML data"`

The `-m` flag tells Git that you're providing a message, which you write in quotes immediately after.

And that's it! Now, you can see your commit under the `Graph` section.

![First commit.](/assets/git-and-github/git-basics/first-commit.png)

## Updating files

We have XML data, which is not very convenient. It would be better to have JSON data.

Let's install the [`fast-xml-parser`](https://www.npmjs.com/package/fast-xml-parser) from NPM to convert our data.

In your terminal, run: `deno add npm:fast-xml-parser`

Then update your `main.ts`.

```ts showLineNumbers filename="main.ts" {1, 6-9}
import { XMLParser } from "fast-xml-parser";

const response = await fetch(
"https://dd.weather.gc.ca/observations/swob-ml/latest/CWTQ-AUTO-minute-swob.xml",
);
const xml = await response.text();
const json = new XMLParser({ ignoreAttributes: false }).parse(xml);

console.log(json);
```

Now, you’ll see more changes. Because we installed a library, Deno created a `deno.json` and a `deno.lock` file. They are green and untracked.

But `main.ts` is yellow with an `M` next to it. This is Git telling you the file has been modified.

You can run `deno -A main.ts` just to make sure the code works.

![Files have been modified.](/assets/git-and-github/git-basics/changes.png)

You can check the changes line by line in the file. Next to the line numbers, you’ll see colored gutters:
- Green means the line is new
- Blue means the line has been modified
- Red means the line has been removed

If you click on the gutters, you’ll see the details. Additions are shown in green, deletions in red. If you want to go back to the previous version, click on the rollback arrow.

![Inspecting the changes in the file.](/assets/git-and-github/git-basics/inspecting-changes.png)

You can also see all the differences in the `Source Control` tab. Click on `main.ts` to view the `Working Tree`.

For example, here we can clearly see that we are using a new library (green lines on the right) and that we removed `console.log(xml)` (in red on the left).

If you want to roll back to a previous version of the file, you can also click the rollback arrow under `Changes`.

![Inspecting the changes in the file with the working tree.](/assets/git-and-github/git-basics/working-tree.png)

Let's commit these changes:
- Run `git add -A`
- Then `git commit -m "XML to JSON"`

Now, you can see your second commit in the `Graph`. And if you click on it, you can view all the changes made compared to the previous commit.

Make sure to scroll to see the changes in `deno.json`, `deno.lock`, and `main.ts`.

![Inspecting all the changes for a commit.](/assets/git-and-github/git-basics/second-commit.png)

## Reverting a commit

One very powerful feature of Git is the ability to easily roll back to a previous commit.

For example, let's create an error in our code. Let’s parse the fetch response as JSON instead of text in `main.ts`.

```ts showLineNumbers filename="main.ts" /.json()/
import { XMLParser } from "fast-xml-parser";

const response = await fetch(
"https://dd.weather.gc.ca/observations/swob-ml/latest/CWTQ-AUTO-minute-swob.xml",
);
const xml = await response.json();
const json = new XMLParser({ ignoreAttributes: false }).parse(xml);

console.log(json);
```
Let's commit this before testing it 😱:
- `git add -A`
- `git commit -m "Parsing response as JSON"`

And then let's test our new code with `deno -A main.ts`.

![A third commit.](/assets/git-and-github/git-basics/error.png)

Oh no! It crashes! And we’ve committed! How do we roll back?

Of course, you could always check the changes and update the code manually. But if you're working on a big project, this might not always be realistic. Instead, you can use the `git revert` command with a commit ID.

To retrieve a commit ID, right-click on the commit and click on `Copy Commit ID`. Here, the commit we want to revert is the latest one.

![Copying a commit ID](/assets/git-and-github/git-basics/copy-id.png)

Then start typing `git revert` in the terminal, paste the commit ID (don't forget a space between `revert` and your commit ID), and run the command!

What you’re seeing in your terminal is a text editor. The lines above the `#` section are the suggested commit message.

![Reverting a commit.](/assets/git-and-github/git-basics/revert.png)

To accept the suggested commit, just type `:q` in the terminal and press Enter to confirm and quit the terminal text editor. You can also click on the big blue `Commit` button.

Now, you'll see a fourth commit, indicating that you reverted! For a *real* rollback, you can also use [`git reset`](https://git-scm.com/docs/git-reset), but reverting is safer and keeps a history of everything—including the revert!

Now, if you run `deno -A main.ts`, everything works like before this silly code mistake.

![A reverted commit.](/assets/git-and-github/git-basics/reverted.png)

## Branches

Another important concept in Git is **branches**.

By default, a repository has a `main` branch. You can see your branch in the bottom-left corner of VS Code and next to your commits. So far, we've been working on `main`.

![The main branch on VS Code.](/assets/git-and-github/git-basics/main-branch.png)

Usually, we (try 😅) to keep `main` clean and work on branches instead.

For example, let's say we now want to extract the date and temperature from the data we fetched for Montreal. We could create a new branch to add this code to the project.

### Adding a branch

To create a new branch named `temperature`, run: `git checkout -b temperature`

The `checkout` command tells Git you want to switch to another branch. The `-b` followed by `temperature` tells it to create the new branch `temperature` before switching to it. Because you are on `main`, the branch will be created from `main`. The code will be exactly the same on both branches at first.

If you want to see a list of all branches, you can run `git branch`. The one with a `*` in front of it is the branch you're currently on.

![The temperature branch on VS Code.](/assets/git-and-github/git-basics/new-branch.png)

### Working on a branch

We can now update our code in `main.ts`. The data is a deeply nested JSON, but retrieving the `resultTime` and the `temperature` is straightforward.

If you run `deno -A main.ts`, you should see the temperature logged in the terminal.

```ts showLineNumbers filename="main.ts" {9-23}
import { XMLParser } from "fast-xml-parser";

const response = await fetch(
"https://dd.weather.gc.ca/observations/swob-ml/latest/CWTQ-AUTO-minute-swob.xml",
);
const xml = await response.text();
const json = new XMLParser({ ignoreAttributes: false }).parse(xml);

const observation =
json["om:ObservationCollection"]["om:member"]["om:Observation"];

const resultTime =
observation["om:resultTime"]["gml:TimeInstant"]["gml:timePosition"];
console.log(resultTime);

const elements = observation["om:result"]["elements"]["element"];
type element = {
"@_name": string;
"@_value": string;
};
const temp = elements
.find((d: element) => d["@_name"] === "air_temp")["@_value"];
console.log(temp);
```

Let's commit this update:
- `git add -A`
- `git commit -m "Extracting temp and time"`

![Working on the temperature branch.](/assets/git-and-github/git-basics/commit-new-branch.png)

This has been committed to the `temperature` branch. The `main` branch has not changed. To check the `main` branch, you can use `git checkout main`.

As you can see, our new code is not there! In case we created an error or introduced a new bug on the `temperature` branch, we know that `main` won't have it.

This is why branches are so great: you can work confidently on them. You can test and break things without worrying about your previous achievements—they're kept safe! Branches are also very useful when multiple people are collaborating. Each one can work on their own thing in their own branch.

![Checking out the main branch.](/assets/git-and-github/git-basics/checkout-main.png)

### Merging branches

Now, let's say we are happy with our new code on the `temperature` branch. We would like to bring it to the `main` branch.

To do that, we have to **merge** the branches.

Make sure you are on the `main` branch (`git checkout main`) and then run `git merge temperature`. This command will merge the `temperature` branch into the `main` branch.

Now, the new code is on `main`! And you can see the commit that we created in `temperature`. The history has been merged.

![Merging the main branch.](/assets/git-and-github/git-basics/merge-main.png)

### Deleting branches

We don't need the `temperature` branch anymore. Let's remove it by running: `git branch -d temperature`

As you can see, the syntax is the same as when creating a branch, except the option is `-d` instead of `-b`. Be careful! 😬

Now, if you run `git branch`, you won’t see `temperature` anymore.

![Deleting the temperature branch.](/assets/git-and-github/git-basics/delete-branch.png)

## Removing git

If, for some reason, you need to remove Git from one of your projects, you must delete the hidden `.git` folder.

You can do that with your file explorer.

![A hidden git folder.](/assets/git-and-github/git-basics/git-folder.png)

Or you can do it in your terminal with this command: `rm -fr .git`

But you need to be **extremely careful** when running it. This command deletes everything recursively. It could wipe out your entire computer. You must ensure you are in your project folder and be careful of typos.

## Conclusion

Congratulations! You've learned the most important Git commands:
- `git init` to start a new Git repository
- `git add -A` to track the files
- `git commit -m "A message"` to save the project
- `git revert commitID` to revert a commit
- `git branch -b my-new-branch` to create a new branch
- `git checkout my-new-branch` to switch to a different branch
- `git merge my-new-branch` to merge branches
- `git branch -d my-new-branch` to delete a branch

These eight commands will cover 95% of your daily needs.

Of course, our use case here was quite simple. Things can get more complicated when multiple people work at the same time on different branches and conflicts between branches can happen. But this should be enough to get you started on your Git journey!

By the way, Git is great with any text-based files, but you can also track images, videos, and more!

And one last piece of advice: commit often, and always assume your commit messages are public. You never know when you'll be asking a colleague for help! And if you're working on an open-source project—well, everyone will see your commits! 😅

Now, using Git is great, but so far we've kept everything on our computer. In the next lesson, we'll talk about GitHub, which can store your code in the cloud for free!

<NoticeEnd />
1 change: 1 addition & 0 deletions pages/fr/_meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default {
"d3-chart": "Graphiques animés avec D3 🧑‍🎨",
"d3-map": "Cartes animées avec D3 🗺️",
"web-scraping": "Extraction de données web 🔍",
"git-and-github": "5. Git et GitHub 🐙",
"ninja-moves": "Techniques de ninja 🥷",
inspirations: "Personnes & contenus inspirants 📚",
"more": "Prochaines leçons...",
Expand Down
3 changes: 3 additions & 0 deletions pages/fr/git-and-github/_meta.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
"git-basics": "Comment utiliser Git?",
};
Loading