# Basic Git Commands: init, status, add, commit, log<no value>

## What will we learn?

The daily work cycle with Git, command by command:

| Command | What it does |
|---|---|
| `git init` | Creates a Repository |
| `git status` | What is the state now? |
| `git add` | Puts changes into Staging |
| `git commit` | Saves a snapshot into the history |
| `git log` | Shows the history |
| `git diff` | Shows what changed |

And in addition: **`.gitignore`**, how to tell Git "ignore these".

## Why do we need this?

These are the commands developers run **dozens of times a day**. From now on, every exercise and every project in the course will be managed in Git: first because it is a professional habit, and second because in the OOP projects and in the integration project the history will save you when something breaks.

## Explanation from the basics

### The work cycle

```text
1. edit files          (Working Directory changes)
2. git status          (see what changed)
3. git add <files>     (choose what goes into the snapshot)
4. git commit -m "..." (save the snapshot)
5. repeat
```

### `git status` — the most important command

`git status` changes nothing. It only **tells** you the state: what is Untracked, what is Modified, what is Staged. **Golden rule: before every `add` and before every `commit`, run `git status`.**

### The Commit message

The message explains **what** changed and **why**, for whoever reads the history (including you in a month). We will go deeper into the rules in the next lesson. For now: a short sentence in English, in the imperative: `"Add discount calculation"`, `"Fix crash on empty cart"`.

### `.gitignore`

Not every file should go into the Repository:

- **Files that are created automatically**: `__pycache__/`, `*.pyc`.
- **Personal or secret information**: passwords, API keys, `.env` files. They **must not** reach GitHub!
- **Local work files**: logs (`*.log`), a local Database, virtual environments (`venv/`, we will meet them in the backend and databases topics).
- **System files**: `.DS_Store` (Mac), `Thumbs.db` (Windows).

A file named `.gitignore` in the project folder contains **patterns** (one line per pattern), and Git simply does not "see" files that match them.

## Syntax

```powershell
git init                          # create a repository in the current folder
git status                        # show the state of files
git add file.py                   # stage one file
git add folder/                   # stage everything in a folder
git add .                         # stage ALL changes in the current folder (check status first!)
git commit -m "Short message"     # commit staged changes with a message
git log                           # full history (press q to quit)
git log --oneline                 # compact history, one line per commit
git diff                          # changes NOT yet staged
git diff --staged                 # changes that ARE staged (will go into the commit)
git restore --staged file.py      # un-stage a file (keeps your edits)
```

**An example `.gitignore` for a Python project:**

```text
# Python cache
__pycache__/
*.pyc

# Local data and logs
*.log
*.db

# Secrets and environments
.env
venv/

# OS files
.DS_Store
Thumbs.db
```

`#` = a comment. `*` = "anything". A line that ends with `/` = a folder.

## First code example

A full work cycle, from zero. Inside `kodkod6`:

```powershell
mkdir calculator
cd calculator
git init
```

Create `calculator.py`:

```python
def add(a, b):
    return a + b
```

And now:

```powershell
git status
git add calculator.py
git status
git commit -m "Add calculator with add function"
git log --oneline
```

**Output:**

```text
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        calculator.py

nothing added to commit but untracked files present (use "git add" to track)
```

```text
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   calculator.py
```

```text
[main (root-commit) 4e7a1c2] Add calculator with add function
 1 file changed, 2 insertions(+)
 create mode 100644 calculator.py
```

```text
4e7a1c2 (HEAD -> main) Add calculator with add function
```

## Breaking down the code line by line

| Output | Meaning |
|---|---|
| `On branch main` | We are on the main branch `main`. (Branches are an advanced topic, which we will not deal with right now.) |
| `No commits yet` | The Repository is new, and there is no history. |
| `Untracked files: calculator.py` | Git sees a new file, but does not track it. |
| `Changes to be committed: new file` | After `add`: the file is in Staging, and will go into the next Commit. |
| `[main (root-commit) 4e7a1c2]` | A Commit was created. `root-commit` = the first one in the history. `4e7a1c2` = the start of its Hash. |
| `1 file changed, 2 insertions(+)` | A summary: one file, 2 lines were added. |
| `(HEAD -> main)` | **HEAD** = "where we are now", the last Commit on the branch `main`. |

**Notice:** `git status` itself suggests what to do (`use "git add <file>..."`). Read its hints!

## Another example

**A change, diff, and a second Commit.** Add to `calculator.py`:

```python
def subtract(a, b):
    return a - b
```

```powershell
git status
git diff
git add calculator.py
git commit -m "Add subtract function"
git log
```

**`git status`:**

```text
Changes not staged for commit:
        modified:   calculator.py
```

**`git diff`:**

```text
diff --git a/calculator.py b/calculator.py
--- a/calculator.py
+++ b/calculator.py
@@ -1,2 +1,6 @@
 def add(a, b):
     return a + b
+
+
+def subtract(a, b):
+    return a - b
```

**`git log`:**

```text
commit 9d02b6f5e1a8c7d3b4f2e6a9c0d1e8b7f6a5c4d3 (HEAD -> main)
Author: Dana Cohen <dana@example.com>
Date:   Tue Oct 6 11:20:41 2026 +0300

    Add subtract function

commit 4e7a1c2b8f0d6e5a3c1b9d7f4e2a0c8b6d5f3e1a
Author: Dana Cohen <dana@example.com>
Date:   Tue Oct 6 11:05:12 2026 +0300

    Add calculator with add function
```

**Breakdown:**

- `modified:` — the file is **known** to Git (it was in a Commit), and it changed.
- In `git diff`, a line that starts with `+` **was added**, a line with `-` **was deleted**, and a line with a space is context that did not change. `@@ -1,2 +1,6 @@` = "lines 1–2 in the old version became lines 1–6 in the new one".
- `git log` shows from newest to oldest: the full Hash, the author, the date and the message. **To leave a long `git log`: the `q` key.**

**And now `.gitignore`:** run the code once (`python -c "import calculator"`), and `git status` will show `__pycache__/` as Untracked. Create a `.gitignore` with `__pycache__/`, and `git status` will no longer show it. Don't forget: `git add .gitignore` and a Commit. The file itself **should** be in the Repository.

## Common mistake

**Mistake 1: `git add .` without checking `status`.** `add .` adds **everything**, including log files, `__pycache__`, and worst of all, files with passwords. **First `git status`, first `.gitignore`, and only then `add .`.**

And if you added something to Staging by mistake:

```powershell
git restore --staged secrets.txt
```

The file leaves Staging, and the changes in it remain.

**Mistake 2: a Commit without `-m`.** `git commit` alone opens a text editor for the message. If you did not set `core.editor`, it will usually open **Vim**, an editor that is "hard to get out of". If you got stuck in Vim: `Esc`, then type `:q!` and Enter (quit without saving), and then run again with `-m "..."`.

**Mistake 3: meaningless messages.**

```text
a1b2c3d fix
e4f5a6b stuff
c7d8e9f asdf
f0a1b2c final
```

In a month, nobody will understand what happened in this history. Every Commit is "a letter to the future".

**Mistake 4: adding to `.gitignore` a file that was already committed.** `.gitignore` affects only files that Git **does not track yet**. If `app.log` is already in the Repository, you also need to stop tracking it: `git rm --cached app.log`, and then a Commit.

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## Practice

The exercises use only what was taught in this lesson and the lessons before it. Try on your own first, and only then open the solution.

### Exercise 1: A first Commit

A new folder has a file `calculator.py`. Write the sequence of commands that creates a Repository, checks the state, adds the file and makes a first Commit with a suitable message.

{{< solution >}}
```powershell
git init
git status
git add calculator.py
git commit -m "Add calculator with add and subtract"
git status
```

- `git init` — creates a Repository.
- The first `git status` — shows that `calculator.py` is **Untracked**.
- `git add` — moves it to the Staging Area.
- `git commit -m` — saves a snapshot with a message.
- `git status` at the end — shows **nothing to commit, working tree clean**.
{{< /solution >}}

### Exercise 2: Reading git status

```text
Changes to be committed:
        modified:   calculator.py

Changes not staged for commit:
        modified:   README.md

Untracked files:
        notes.txt
```

For each file — what state is it in, and what will happen to it if you now run `git commit -m "Update"`?

{{< solution >}}
| File | State | In the next Commit? |
|---|---|---|
| `calculator.py` | The change is in the **Staging Area** | **Yes** |
| `README.md` | Changed, but **not** added with `git add` | No |
| `notes.txt` | **Untracked** — Git does not track it at all | No |

Only what is in the Staging Area goes into the Commit.
{{< /solution >}}

### Exercise 3: .gitignore

A Python project has:

```text
main.py
calculator.py
__pycache__/
secrets.txt        (passwords)
app.log
README.md
```

Write a suitable `.gitignore` file, and explain why each line is in it.

{{< solution >}}
```text
# Python cache
__pycache__/
*.pyc

# Passwords and keys
secrets.txt

# Logs
*.log
```

- `__pycache__/` — files Python creates automatically. There is no reason to keep them.
- `secrets.txt` — **passwords do not go into Git**, ever. What goes into the history stays in it.
- `*.log` — logs change on every run and belong to the computer they ran on.

`main.py`, `calculator.py` and `README.md` are the project itself — they **do** go in.
{{< /solution >}}

### Exercise 4: Reading git diff

```text
-def add(a, b):
-    return a - b
+def add(a, b):
+    return a + b
```

1. What do the lines that start with `-` and `+` mean?
2. What is the actual change, and which Commit message suits it?

{{< solution >}}
1. **`-`** — a line that was there and was deleted. **`+`** — a new line that was added.
2. The function `add` subtracted instead of adding, and the change fixes that. A suitable message: `Fix add returning a - b`.

`git diff` shows what changed **before** `git add` — it is worth running it before every Commit, to make sure only what you intended goes in.
{{< /solution >}}

### Exercise 5: History with git log

```text
e91d5aa Fix VAT rounding
7b2e004 Add price calculator
a3f9c21 Initial project
```

1. Which command shows the history with one line per Commit?
2. Which is the oldest Commit, and which is the latest?
3. Add the function `multiply` and then `divide`. How many Commits would you make, and why?

{{< solution >}}
1. `git log --oneline`.
2. The oldest: `a3f9c21 Initial project` (at the bottom). The latest: `e91d5aa Fix VAT rounding` (at the top).
3. **Two Commits** — one for each function: `Add multiply` and then `Add divide`. That way every Commit is one change, and the history tells a clear story. If `divide` turns out to be problematic, it is easy to see exactly when and what was added.
{{< /solution >}}

<!-- exercises:end -->

## Summary

- The cycle: **edit → `git status` → `git add` → `git commit -m "..."`**.
- `git status` = "what is the state?". Run it before every action, and read its hints.
- `git log --oneline` = history. `git diff` = what changed (`--staged` = what will go into the Commit).
- `git add .` only after `status` and `.gitignore`. `git restore --staged` takes a file out of Staging.
- **`.gitignore`**: `__pycache__/`, logs, `.env`, secrets. It goes into the Repository itself.

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

## Official documentation

- [Pro Git — Getting a Git Repository](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository)
- [Pro Git — Recording Changes](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository)
- [Pro Git — Viewing the Commit History](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History)

<!-- docs:end -->
