# GitHub, Remote и Push — и хорошие сообщения Commit<no value>

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

- Что такое **GitHub**.
- Что такое **Remote** (удалённый сервер) и что такое **origin**.
- Как **загружать** код с помощью **`git push`**.
- Как писать хорошие **сообщения Commit**.

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

До сих пор вся история хранится **только на вашем компьютере**. GitHub даёт:

- **Резервную копию в облаке** — ноутбук сломался? Код в безопасности.
- **Возможность поделиться** — вы отправляете ссылку преподавателю, коллегам по команде, работодателю.
- **Портфолио** — ваш профиль на GitHub — это профессиональное резюме разработчика. Рекрутеры **действительно** на него смотрят.
- **Командную работу** — вся команда синхронизирует код через один и тот же репозиторий.

С сегодняшнего дня каждый проект курса (включая проекты ООП и интеграционный проект) загружается на GitHub.

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

### GitHub

**GitHub** — сайт (и сервис), который хранит репозитории Git **на сервере**. Это **сервер** в том смысле, который мы изучили в теме о компьютере, операционной системе и сети: ваш локальный Git — **клиент**, и он отправляет Commit на GitHub по **HTTPS**.

(Есть и похожие сервисы: GitLab и Bitbucket. Идея та же.)

### Remote и origin

**Remote** = адрес **другой копии** репозитория, которая находится где-то ещё, обычно на GitHub. Remote дают **псевдоним**, и по соглашению главный Remote называется **`origin`**.

```text
Your computer                              GitHub
┌──────────────────────┐   git push    ┌──────────────────────┐
│ Local repository     │ ────────────► │ Remote repository    │
│ (.git, all commits)  │               │ "origin"             │
└──────────────────────┘ ◄──────────── └──────────────────────┘
                           git pull
```

- **`git push`** — **отправляет** локальные Commit, которых ещё нет на Remote.
- **`git pull`** — **скачивает** новые Commit с Remote (когда кто-то другой сделал push или когда вы работали с другого компьютера). Сейчас мы не будем в это углубляться.
- **`git clone <url>`** — скачивает **существующий** репозиторий с GitHub на компьютер вместе со всей историей.

{{< box "analogy" "Аналогия: фотоальбом и резервная копия в облаке" >}}
Локальный репозиторий — фотоальбом на вашем телефоне. **`commit`** = сделать фото (сохранено на телефоне). **`push`** = синхронизация с облаком. Если телефон потеряется, фото, которые были синхронизированы, в безопасности, а остальные потеряны. Поэтому: **делайте commit часто, а push — в конце каждой единицы работы.**
{{< /box >}}

### Аутентификация

GitHub должен знать, что вам разрешено делать push в репозиторий. В Windows и Mac при первом push **в браузере открывается окно входа** (Git Credential Manager), вы входите один раз, и система запоминает. **GitHub не принимает пароль аккаунта в терминале**. Если в терминале у вас спрашивают «Password», нужен **Personal Access Token** (увидим в типичных ошибках).

### Хорошие сообщения Commit

| Правило | ✗ Не так | ✓ Так |
|---|---|---|
| **Повелительное наклонение, настоящее время** («что делает Commit») | `Added login` | `Add login form` |
| **Конкретно** | `fix bug` | `Fix crash when cart is empty` |
| **Коротко** (первая строка до ~50 символов) | `I changed the function that calculates the total because...` | `Apply VAT after discount in total` |
| **Одно логическое изменение** | `Add login, fix typos, update colors` | Три отдельных Commit |
| **На английском** (принятое в индустрии соглашение) | | |

**Проверка:** закончите предложение «If applied, this commit will **___**». `Add login form` ✓. `Added login` ✗.

## Синтаксис

**Подключение существующего локального репозитория к GitHub и первый push:**

```powershell
git remote add origin https://github.com/USERNAME/REPO-NAME.git
git branch -M main
git push -u origin main
```

**После этого — каждый раз:**

```powershell
git add ...
git commit -m "..."
git push
```

**Вспомогательные команды:**

```powershell
git remote -v                  # show configured remotes
git clone https://github.com/USERNAME/REPO-NAME.git   # download an existing repo
```

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

**Загружаем проект `calculator` из предыдущего урока на GitHub шаг за шагом:**

**Шаг 1 — аккаунт.** Зайдите на [github.com](https://github.com) → **Sign up**. Профессиональное имя пользователя (оно будет в вашем резюме!). Рекомендуется использовать тот же email, который вы задали в `git config`.

**Шаг 2 — новый репозиторий.** На сайте: **+** (вверху) → **New repository**:

- **Repository name:** `calculator`
- **Public** (видно всем) или **Private**.
- **Не** отмечайте «Add a README», «.gitignore» или «license». У нас уже есть локальный репозиторий, и мы хотим начать с **пустого** Remote.
- **Create repository**.

**Шаг 3 — подключение и push.** GitHub показывает команды. Из папки `calculator`:

```powershell
git remote add origin https://github.com/dana-cohen/calculator.git
git branch -M main
git push -u origin main
```

**Вывод:**

```text
Enumerating objects: 18, done.
Counting objects: 100% (18/18), done.
Delta compression using up to 8 threads
Compressing objects: 100% (16/16), done.
Writing objects: 100% (18/18), 1.92 KiB | 1.92 MiB/s, done.
Total 18 (delta 4), reused 0 (delta 0), pack-reused 0
To https://github.com/dana-cohen/calculator.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.
```

**Шаг 4 — проверка.** Обновите страницу репозитория на GitHub. Файлы там! Щёлкните **Commits**, чтобы увидеть всю историю с сообщениями, которые вы написали.

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

| Команда | Объяснение |
|---|---|
| `git remote add origin <url>` | «Зарегистрируй Remote с именем `origin` по этому адресу». Только регистрирует, ничего не отправляет. |
| `git branch -M main` | Гарантирует, что текущая ветка называется `main`. (Если вы задали `init.defaultBranch main`, она уже так называется, и команда не вредит.) |
| `git push -u origin main` | **Отправляет** ветку `main` в `origin`. `-u` (upstream) устанавливает связь между ними, чтобы дальше хватало `git push`. |
| `Writing objects: 100%` | Commit и файлы отправляются (в сжатом виде) на сервер. |
| `* [new branch] main -> main` | Ветка `main` создана на GitHub с вашей историей. |

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

**Полный рабочий цикл после подключения** — изменение, Commit, Push и проверка на сайте:

```powershell
git status
git add calculator.py
git commit -m "Add power function"
git push
git status
```

В `calculator.py`:

```python
def power(base, exponent):
    return base ** exponent
```

**Вывод `git push`:**

```text
To https://github.com/dana-cohen/calculator.git
   b81c0f4..e2f7a90  main -> main
```

**Вывод `git status` после push:**

```text
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
```

**Разбор:**

- `b81c0f4..e2f7a90` — ветка на GitHub «продвинулась» от предыдущего Commit к новому.
- `Your branch is up to date with 'origin/main'` — локальная копия и Remote **синхронизированы**. До push `git status` написал бы `Your branch is ahead of 'origin/main' by 1 commit`, то есть «у вас есть Commit, который ещё не загружен».
- На сайте в `calculator.py` видна новая функция, а в истории — `Add power function`.

### README.md — визитная карточка проекта

GitHub автоматически показывает файл `README.md` на главной странице репозитория. Пишите его в каждом проекте:

```text
# Calculator

A simple Python calculator - Kodkod 6 intro course, week 2.

## How to run

    python main.py

## Functions

- add, subtract, multiply, divide, power
```

Файл пишется в формате **Markdown**: `#` = заголовок, `-` = список. А затем: `git add README.md`, `git commit -m "Add README"`, `git push`.

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

**Ошибка 1: GitHub спрашивает пароль в терминале, и пароль «не работает».**

```text
remote: Support for password authentication was removed on August 13, 2021.
fatal: Authentication failed for 'https://github.com/...'
```

GitHub не принимает пароль аккаунта в терминале. Рекомендуемое решение: Git для Windows и Mac поставляется с **Git Credential Manager**, который открывает окно входа в браузере. Если оно не открывается, создайте **Personal Access Token**: на сайте → Settings → Developer settings → Personal access tokens. Вставьте Token вместо пароля.

**Ошибка 2: Remote создан с README, и push отклоняется.**

```text
! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/...'
hint: Updates were rejected because the remote contains work that you do not have locally.
```

При создании репозитория на сайте вы отметили «Add a README», поэтому на GitHub есть Commit, которого нет у вас. Самое простое решение на этом этапе: удалить репозиторий на сайте (Settings → Delete) и создать его снова **пустым**. («Настоящее» решение — `git pull`, который мы ещё не изучили подробно.)

**Ошибка 3: `remote origin already exists`.**

```text
error: remote origin already exists.
```

Вы уже добавили Remote с таким именем (возможно, с неверным адресом). Проверьте через `git remote -v` и исправьте: `git remote set-url origin <correct-url>`.

**Ошибка 4: push секретов.** Файл с паролем или ключом API, загруженный в **публичный** репозиторий, считается **утёкшим**, даже если удалить его в следующем Commit, потому что он остаётся в истории. Боты сканируют GitHub и находят ключи за минуты. **`.gitignore` — до первого Commit**, а секреты — никогда в коде.

**Ошибка 5: Commit без Push.** «Я сделал Commit, значит, он на GitHub». Нет! Commit только локальный, и загружает только `push`.

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

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

### Упражнение 1: Подключение к GitHub

Вы создали пустой репозиторий на GitHub по адресу `https://github.com/dana-cohen/calculator.git`. На компьютере уже есть локальный репозиторий с Commit. Напишите команды, которые подключают его к GitHub и впервые загружают код.

{{< solution >}}
```powershell
git remote add origin https://github.com/dana-cohen/calculator.git
git branch -M main
git push -u origin main
```

- `git remote add origin ...` — задаёт репозиторий на GitHub как **Remote** с именем `origin`.
- `git branch -M main` — называет главную ветку `main`.
- `git push -u origin main` — загружает Commit. `-u` запоминает связь, и в следующий раз хватит `git push`.
{{< /solution >}}

### Упражнение 2: Локально и на Remote

Дана сделала три Commit на своём компьютере, но не выполнила `git push`. Подруга открывает репозиторий на GitHub.

1. Видит ли она три Commit?
2. Компьютер Даны сломался до того, как она сделала push. Что потеряно?

{{< solution >}}
1. **Нет.** Commit сохраняется только в **локальном** репозитории. GitHub обновляется только после `git push`.
2. Три Commit **потеряны** — они были только на компьютере. Именно поэтому нужен push: **резервная копия** вне компьютера и возможность делиться с другими.
{{< /solution >}}

### Упражнение 3: push, clone и remote

Сопоставьте каждую команду с тем, что она делает:

```text
git push
git clone <url>
git remote add origin <url>
```

(а) Скачивает существующий репозиторий с GitHub на новый компьютер. (б) Задаёт, куда загружать. (в) Загружает Commit на GitHub.

{{< solution >}}
| Команда | Что делает |
|---|---|
| `git push` | (в) — загружает локальные Commit на Remote |
| `git clone <url>` | (а) — скачивает полную копию репозитория вместе со всей историей |
| `git remote add origin <url>` | (б) — задаёт Remote, один раз на репозиторий |
{{< /solution >}}

### Упражнение 4: Хорошие сообщения Commit

Для каждого сообщения — хорошее или нет? Если нет, напишите хорошую версию.

```text
1. fix
2. Add divide function to calculator
3. changes
4. asdf
5. Fix crash when dividing by zero
```

{{< solution >}}
| Сообщение | Хорошее? | Хорошая версия |
|---|---|---|
| `fix` | Нет — не сказано, что исправлено | `Fix rounding in VAT calculation` |
| `Add divide function to calculator` | **Да** | — |
| `changes` | Нет — любой Commit — это «изменения» | `Update README with run instructions` |
| `asdf` | Нет — бессмысленно | `Add input validation for age` |
| `Fix crash when dividing by zero` | **Да** | — |

Хорошее сообщение: **короткое предложение в повелительном наклонении, описывающее, что делает изменение**.
{{< /solution >}}

### Упражнение 5: Ежедневная рутина

Вы добавили в проект функцию `power`. Расставьте команды в правильном порядке:

```text
git push
git commit -m "Add power function"
git status
git add calculator.py
```

{{< solution >}}
```powershell
git status
git add calculator.py
git commit -m "Add power function"
git push
```

1. `git status` — посмотреть, что изменилось.
2. `git add` — выбрать, что войдёт.
3. `git commit` — сохранить локальный снимок.
4. `git push` — загрузить на GitHub.

Это цикл каждого рабочего дня.
{{< /solution >}}

<!-- exercises:end -->

## Итоги

- **GitHub** = сервер, который хранит репозитории в облаке. Локальный Git общается с ним по HTTPS.
- **Remote** = удалённая копия. **origin** = принятый псевдоним для главной.
- Первое подключение: `git remote add origin <url>` → `git push -u origin main`. Дальше: `git push`.
- **Commit = локально. Push = в облако.** `git status` показывает, «опережаете» ли вы Remote.
- Сообщение Commit: повелительное наклонение, конкретно, коротко, одно изменение, на английском. «If applied, this commit will ___».
- Секреты никогда не загружают. `.gitignore` — до первого Commit.

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

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

- [GitHub Docs — Creating an account](https://docs.github.com/en/get-started/start-your-journey/creating-an-account-on-github)
- [Pro Git — Working with Remotes](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes)
- [git push](https://git-scm.com/docs/git-push)
- [GitHub Docs — About READMEs](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes)

<!-- docs:end -->
