# Базовые команды Git: init, status, add, commit, log<no value>

## Что мы изучим?

Ежедневный рабочий цикл с Git, команда за командой:

| Команда | Что делает |
|---|---|
| `git init` | Создаёт репозиторий |
| `git status` | Каково сейчас состояние? |
| `git add` | Помещает изменения в Staging |
| `git commit` | Сохраняет снимок в историю |
| `git log` | Показывает историю |
| `git diff` | Показывает, что изменилось |

И дополнительно: **`.gitignore`** — как сказать Git «игнорируй это».

## Зачем это нужно?

Это команды, которые разработчики выполняют **десятки раз в день**. Отныне каждое упражнение и каждый проект курса будут вестись в Git: во-первых, потому что это профессиональная привычка, а во-вторых, потому что в проектах ООП и в интеграционном проекте история спасёт вас, когда что-то сломается.

## Объяснение с основ

### Рабочий цикл

```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` — самая важная команда

`git status` ничего не меняет. Она только **сообщает** состояние: что Untracked, что Modified, что Staged. **Золотое правило: перед каждым `add` и перед каждым `commit` выполняйте `git status`.**

### Сообщение Commit

Сообщение объясняет, **что** изменилось и **зачем**, для того, кто будет читать историю (включая вас через месяц). Подробнее о правилах — в следующем уроке. Пока: короткое предложение на английском в повелительном наклонении: `"Add discount calculation"`, `"Fix crash on empty cart"`.

### `.gitignore`

Не каждый файл должен попасть в репозиторий:

- **Файлы, которые создаются автоматически**: `__pycache__/`, `*.pyc`.
- **Личная или секретная информация**: пароли, ключи API, файлы `.env`. Они **не должны** попасть на GitHub!
- **Локальные рабочие файлы**: логи (`*.log`), локальная база данных, виртуальные окружения (`venv/`, мы встретим их в темах бэкенда и баз данных).
- **Системные файлы**: `.DS_Store` (Mac), `Thumbs.db` (Windows).

Файл с именем `.gitignore` в папке проекта содержит **шаблоны** (по одному на строку), и Git просто не «видит» соответствующие им файлы.

## Синтаксис

```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)
```

**Пример `.gitignore` для проекта на Python:**

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

# Local data and logs
*.log
*.db

# Secrets and environments
.env
venv/

# OS files
.DS_Store
Thumbs.db
```

`#` = комментарий. `*` = «что угодно». Строка, которая заканчивается на `/`, = папка.

## Первый пример кода

Полный рабочий цикл с нуля. Внутри `kodkod6`:

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

Создайте `calculator.py`:

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

А теперь:

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

**Вывод:**

```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
```

## Разбор кода построчно

| Вывод | Значение |
|---|---|
| `On branch main` | Мы на главной ветке `main`. (Ветки — продвинутая тема, которой мы сейчас заниматься не будем.) |
| `No commits yet` | Репозиторий новый, истории нет. |
| `Untracked files: calculator.py` | Git видит новый файл, но не отслеживает его. |
| `Changes to be committed: new file` | После `add`: файл в Staging и войдёт в следующий Commit. |
| `[main (root-commit) 4e7a1c2]` | Создан Commit. `root-commit` = первый в истории. `4e7a1c2` = начало его Hash. |
| `1 file changed, 2 insertions(+)` | Итог: один файл, добавлено 2 строки. |
| `(HEAD -> main)` | **HEAD** = «где мы сейчас», последний Commit на ветке `main`. |

**Обратите внимание:** `git status` сам подсказывает, что делать (`use "git add <file>..."`). Читайте его подсказки!

## Ещё один пример

**Изменение, diff и второй Commit.** Добавьте в `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
```

**Разбор:**

- `modified:` — файл **известен** Git (он был в Commit), и он изменился.
- В `git diff` строка, которая начинается с `+`, **добавлена**, строка с `-` **удалена**, а строка с пробелом — неизменный контекст. `@@ -1,2 +1,6 @@` = «строки 1–2 старой версии стали строками 1–6 новой».
- `git log` показывает от новых к старым: полный Hash, автора, дату и сообщение. **Чтобы выйти из длинного `git log`: клавиша `q`.**

**А теперь `.gitignore`:** запустите код один раз (`python -c "import calculator"`), и `git status` покажет `__pycache__/` как Untracked. Создайте `.gitignore` с `__pycache__/`, и `git status` перестанет его показывать. Не забудьте: `git add .gitignore` и Commit. Сам этот файл **должен** быть в репозитории.

## Типичная ошибка

**Ошибка 1: `git add .` без проверки `status`.** `add .` добавляет **всё**, включая логи, `__pycache__` и, хуже всего, файлы с паролями. **Сначала `git status`, сначала `.gitignore`, и только потом `add .`.**

А если вы по ошибке добавили что-то в Staging:

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

Файл уходит из Staging, а изменения в нём остаются.

**Ошибка 2: Commit без `-m`.** Один `git commit` открывает текстовый редактор для сообщения. Если вы не настроили `core.editor`, обычно откроется **Vim** — редактор, из которого «трудно выйти». Если вы застряли в Vim: `Esc`, затем наберите `:q!` и Enter (выйти без сохранения), а потом запустите снова с `-m "..."`.

**Ошибка 3: бессмысленные сообщения.**

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

Через месяц никто не поймёт, что происходило в этой истории. Каждый Commit — «письмо в будущее».

**Ошибка 4: добавить в `.gitignore` файл, который уже был закоммичен.** `.gitignore` действует только на файлы, которые Git **ещё не отслеживает**. Если `app.log` уже в репозитории, нужно ещё и прекратить его отслеживать: `git rm --cached app.log`, а затем Commit.

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## Практика

Упражнения опираются только на то, что пройдено в этом уроке и в предыдущих. Сначала попробуйте сами, и только потом открывайте решение.

### Упражнение 1: Первый Commit

В новой папке есть файл `calculator.py`. Напишите последовательность команд, которая создаёт репозиторий, проверяет состояние, добавляет файл и делает первый Commit с подходящим сообщением.

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

- `git init` — создаёт репозиторий.
- Первый `git status` — показывает, что `calculator.py` **Untracked**.
- `git add` — переносит его в Staging Area.
- `git commit -m` — сохраняет снимок с сообщением.
- `git status` в конце — показывает **nothing to commit, working tree clean**.
{{< /solution >}}

### Упражнение 2: Читаем git status

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

Changes not staged for commit:
        modified:   README.md

Untracked files:
        notes.txt
```

Для каждого файла — в каком он состоянии и что с ним будет, если сейчас выполнить `git commit -m "Update"`?

{{< solution >}}
| Файл | Состояние | Войдёт в следующий Commit? |
|---|---|---|
| `calculator.py` | Изменение в **Staging Area** | **Да** |
| `README.md` | Изменён, но **не** добавлен через `git add` | Нет |
| `notes.txt` | **Untracked** — Git его вообще не отслеживает | Нет |

В Commit входит только то, что находится в Staging Area.
{{< /solution >}}

### Упражнение 3: .gitignore

В проекте на Python есть:

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

Напишите подходящий файл `.gitignore` и объясните, зачем в нём каждая строка.

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

# Passwords and keys
secrets.txt

# Logs
*.log
```

- `__pycache__/` — файлы, которые Python создаёт автоматически. Хранить их незачем.
- `secrets.txt` — **пароли в Git не кладут**, никогда. Что попало в историю, в ней и остаётся.
- `*.log` — логи меняются при каждом запуске и относятся к компьютеру, на котором он был.

`main.py`, `calculator.py` и `README.md` — сам проект, они **входят**.
{{< /solution >}}

### Упражнение 4: Читаем git diff

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

1. Что означают строки, которые начинаются с `-` и `+`?
2. В чём фактическое изменение и какое сообщение Commit ему подходит?

{{< solution >}}
1. **`-`** — строка, которая была и была удалена. **`+`** — новая строка, которая была добавлена.
2. Функция `add` вычитала вместо сложения, и изменение это исправляет. Подходящее сообщение: `Fix add returning a - b`.

`git diff` показывает, что изменилось **до** `git add`, — его стоит выполнять перед каждым Commit, чтобы убедиться, что входит только то, что вы задумали.
{{< /solution >}}

### Упражнение 5: История с git log

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

1. Какая команда показывает историю по одной строке на Commit?
2. Какой Commit самый старый, а какой последний?
3. Добавьте функцию `multiply`, а затем `divide`. Сколько Commit вы бы сделали и почему?

{{< solution >}}
1. `git log --oneline`.
2. Самый старый: `a3f9c21 Initial project` (внизу). Последний: `e91d5aa Fix VAT rounding` (вверху).
3. **Два Commit** — по одному на каждую функцию: `Add multiply`, а затем `Add divide`. Так каждый Commit — одно изменение, и история рассказывает понятную историю. Если `divide` окажется проблемной, легко увидеть, когда и что именно было добавлено.
{{< /solution >}}

<!-- exercises:end -->

## Итоги

- Цикл: **редактирование → `git status` → `git add` → `git commit -m "..."`**.
- `git status` = «каково состояние?». Выполняйте перед каждым действием и читайте подсказки.
- `git log --oneline` = история. `git diff` = что изменилось (`--staged` = что войдёт в Commit).
- `git add .` — только после `status` и `.gitignore`. `git restore --staged` выводит файл из Staging.
- **`.gitignore`**: `__pycache__/`, логи, `.env`, секреты. Сам он входит в репозиторий.

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

## Официальная документация

- [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 -->
