← Курс для РП

00 · экскурс

Git без боли:
понять один раз, пользоваться каждый день

Git это система контроля версий. Она хранит историю проекта как цепочку снимков, позволяет вернуться к любому из них, вести несколько линий работы параллельно и сливать результаты нескольких людей
без «отправь мне последнюю версию».

→ правки → → → →

Это 90% повседневной работы. Любую команду на странице можно скопировать кликом. Клавиша / — поиск по шпаргалке.

Какую проблему он решает

Без GitС Git
analysis_final_v3_правки_НОВЫЙ.ipynbОдин файл, вся история внутри: кто, когда, что и зачем изменил
«Вчера работало, сегодня нет, что я поменял?»git diff, git log, git bisect находят изменение за минуты
Страшно пробовать новую идею, а вдруг сломаю рабочееВетка: эксперимент изолирован, основа не тронута
Двое правят один файл и затирают друг другаСлияние объединяет правки, конфликты показывает явно
«Какой версией кода обучена эта модель / посчитан отчет?»Хеш коммита однозначно фиксирует состояние кода

Четыре идеи, на которых все держится

01

Коммит = снимок

Не «разница», а полное состояние проекта в момент времени плюс ссылка на предыдущий снимок.
У каждого есть уникальный хеш.

02

Ветка = указатель

Ветка — это просто подвижная метка на коммите. Создать ветку мгновенно и бесплатно, поэтому ими пользуются постоянно.

03

Все локально

У вас полная копия истории. Коммиты, ветки, откаты работают без сети. С сервером вы только синхронизируетесь.

04

Потерять сложно

Закоммиченное почти всегда можно вернуть (см. reflog). Безвозвратно теряется только то, что не было в коммите.

Git ≠ GitHubGit — программа на вашем компьютере. GitHub, GitLab, Gitea, Bitbucket это серверы, где лежит общая копия репозитория
и живут pull/merge request'ы, ревью и CI. Команды Git везде одинаковые.

01 · модельКак устроен Git: четыре места, где живет код

Почти любая команда Git переносит изменения между этими зонами.
Если понимать, откуда и куда, команды перестают быть заклинаниями.

Интерактивная схема: куда команда двигает изменения

Нажмите на команду — стрелка покажет направление, ниже появится объяснение.

Рабочая папка

Обычные файлы на диске. То, что вы видите в редакторе и Jupyter.

Индекс (staging)

Черновик следующего коммита. Позволяет закоммитить не все подряд, а осмысленную часть правок.

Локальный репозиторий

Папка .git: вся история, ветки, теги. Живет рядом с проектом.

Удаленный репозиторий

Общая копия на сервере, обычно под именем origin. Через нее идет обмен с командой.

Состояния файла

СостояниеЧто значитВ git status -s
untrackedНовый файл, Git за ним еще не следит??
modifiedОтслеживается, изменен, не добавлен в индекс M
stagedДобавлен в индекс, войдет в следующий коммитM  / A 
committedСохранен в истории, рабочая папка чистая—
ignoredПодходит под .gitignore, Git его не видит—

02 · стартБыстрый старт: настроить один раз

Представиться и включить полезные настройки

git config --global user.name  "Имя Фамилия"
git config --global user.email "you@company.ru"

git config --global init.defaultBranch main      # новая ветка по умолчанию — main
git config --global pull.rebase true             # pull без лишних merge-коммитов
git config --global push.autoSetupRemote true    # push новой ветки без -u (Git 2.37+)
git config --global fetch.prune true             # убирать ссылки на удаленные ветки
git config --global core.quotepath false         # нормальные кириллические имена файлов
git config --global core.editor "code --wait"    # редактор для сообщений (VS Code)

# Переводы строк: на macOS/Linux — input, на Windows — true
git config --global core.autocrlf input

git config --global --list                       # проверить, что получилось

SSH-ключ, чтобы не вводить пароль

ssh-keygen -t ed25519 -C "you@company.ru"   # Enter, Enter, (пароль по желанию)
cat ~/.ssh/id_ed25519.pub                   # скопировать и добавить в GitHub/GitLab → SSH keys
ssh -T git@github.com                       # проверка (для GitLab: git@gitlab.com)

Получить репозиторий

Проект уже есть на сервере

git clone git@github.com:team/project.git
cd project

Начинаю с нуля в папке

cd my-project
git init
git add .
git commit -m "Initial commit"
git remote add origin git@github.com:me/my-project.git
git push -u origin main      # main — если настроили init.defaultBranch выше
Перед первым коммитомСначала создайте .gitignore (генератор — в разделе Данные и ML), и только потом git add .. Иначе в историю уедут данные, окружение и секреты.

03 · рутинаКаждый день: от задачи до pull request

Один и тот же сценарий подходит и для отчета, и для пайплайна, и для фичи.

  1. Обновить основную ветку
    git switch main
    git pull
    
  2. Создать ветку под задачу
    git switch -c feature/layer-usage-report
    
  3. Работать и смотреть, что изменилось
    git status -sb          # коротко: что изменено, в какой я ветке
    git diff                # что именно изменено (еще не в индексе)
    
  4. Собрать коммит из осмысленных правок
    git add src/report.py   # файл целиком
    git add -p              # или по кусочкам: y — взять, n — пропустить, s — разбить
    git diff --staged       # проверить, что уйдет в коммит
    git commit -m "feat: добавил расчет активности по слоям"
    
  5. Отправить и открыть PR / MR
    git push -u origin feature/layer-usage-report   # -u не нужен, если включили push.autoSetupRemote
    
    Сервер в ответ напечатает ссылку для создания pull/merge request.
  6. После слияния — прибраться
    git switch main
    git pull
    git branch -d feature/layer-usage-report
    
    Если PR влили кнопкой «Squash and merge», Git не поймет, что ветка слита, и откажет. Тогда git branch -D — это безопасно, раз изменения уже в main.

Хороший коммит

Одна мысль — один коммит

«Починил фильтр по дате» и «переименовал колонки» — два разных коммита. Так проще ревьюить и откатывать.

Сообщение отвечает «что и зачем»

fix: убрал дубли пользователей при джойне логов вместо правки или update.

Коммитить часто

Мелкие коммиты — точки сохранения. Перед PR их можно склеить (rebase -i).

Смотреть историю

git log --oneline --graph --decorate --all   # дерево всех веток
git log -5 --stat                            # последние 5 коммитов и затронутые файлы
git log -p -- src/metrics.py                 # вся история правок одного файла
git show a1b2c3d                             # что было в конкретном коммите
git blame -L 40,60 src/metrics.py            # кто и когда менял строки 40–60

04 · веткиВетки, merge и rebase

Ветка — указатель на коммит. HEAD — указатель на то, где вы сейчас. Коммит двигает текущую ветку вперед. Попробуйте руками.

Песочница: граф коммитов

Жмите команды и смотрите, как меняется история. По метке ветки можно кликнуть, чтобы переключиться.

Сценарии:
● коммит▭ ветка (указатель)HEAD→ где вы сейчас◌ пунктир — коммит без ветки, достать можно через reflog

Команды для веток

git branch                    # локальные ветки (* — текущая)
git branch -a -vv             # все ветки + с чем связаны и на сколько расходятся
git switch -c exp/new-features  # создать и перейти
git switch main               # перейти
git switch -                  # вернуться в предыдущую ветку
git branch -m new-name        # переименовать текущую
git branch -d feature/x       # удалить слитую (-D — удалить любую)
git push origin --delete feature/x   # удалить на сервере

Merge или rebase

mergerebase
Что делаетСоединяет две линии истории коммитом слиянияПереносит ваши коммиты поверх другой ветки, создавая их копии
ИсторияЧестная, с развилкамиЛинейная, читается как один поток
Хеши коммитовНе меняютсяМеняются — это новые коммиты
КогдаВлить готовую ветку в main; общие веткиПодтянуть свежий main в свою личную ветку перед PR
Золотое правило rebaseНе делайте rebase веток, с которыми работает кто-то еще. Вы перепишете историю, и у коллег все разъедется. Свою личную ветку — можно и нужно.
# Типичное обновление своей ветки перед PR
git switch feature/x
git fetch origin
git rebase origin/main
git push --force-with-lease      # ветка уже была на сервере → нужна перезапись

05 · серверУдаленный репозиторий

origin — принятое имя сервера. origin/main — ваша локальная «фотография» ветки main на сервере на момент последнего fetch.

git fetch

Скачивает новое с сервера и обновляет origin/*. Ваши ветки и файлы не трогает. Всегда безопасно.

git pull

Это fetch + слияние (или rebase) в текущую ветку. Может вызвать конфликт.

git push

Отправляет ваши коммиты. Если на сервере есть чужие новые коммиты — отклонит, сначала нужен pull.

git remote -v                          # куда смотрит origin
git fetch                              # узнать, что нового, ничего не ломая
git log --oneline HEAD..origin/main    # чего у меня еще нет
git log --oneline origin/main..HEAD    # что я еще не отправил
git pull --rebase                      # забрать и положить свои коммиты сверху
git push                               # отправить
git push --force-with-lease            # перезаписать СВОЮ ветку после rebase/amend
Никогда --force, только --force-with-leaseВторой вариант откажется перезаписывать ветку, если на сервере появились коммиты, которых вы не видели. Обычный --force молча сотрет чужую работу.

Fork-модель (open source, чужие репозитории)

git clone git@github.com:me/project.git                         # свой форк
git remote add upstream git@github.com:original/project.git     # оригинал
git fetch upstream
git rebase upstream/main          # обновить свою ветку от оригинала

06 · отменаОтмена и спасение

Самый востребованный раздел. Ответьте на пару вопросов — получите точную команду.

Мастер «что пошло не так»

Три режима git reset

git reset <режим> HEAD~1 — «отмотать ветку на коммит назад». Режим определяет, что станет с правками из отмененного коммита.

reset, revert, restore — в чем разница

КомандаРаботает сСутьБезопасна для общей ветки
git restoreфайламиВернуть файл к версии из индекса или коммитада (история не меняется)
git revertкоммитамиСоздать новый коммит, отменяющий старыйда
git resetветкойПередвинуть указатель ветки назаднет, только до push

Reflog — страховочная сетка

Git записывает каждое перемещение HEAD. Даже после reset --hard, неудачного rebase или удаления ветки коммиты остаются в хранилище еще как минимум 30 дней (обычно — 90).

git reflog                        # журнал: где был HEAD
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# f4e5d6c HEAD@{1}: commit: важная работа      ← вот он
git reset --hard f4e5d6c          # вернуть ветку на этот коммит
git branch rescue f4e5d6c         # или аккуратнее: повесить на него новую ветку
Что Git не спасетПравки, которые ни разу не попадали в коммит или stash, после git restore, reset --hard и clean -f пропадают окончательно. Последний шанс — локальная история IDE: Timeline в VS Code, Local History в PyCharm.

07 · конфликтыКонфликты слияния

Конфликт — не ошибка. Git просит решить, какая версия правильная, когда две ветки изменили одни и те же строки.

Тренажер: разрешите конфликт

Вы в main и вливаете feature/clean-data. Обе ветки изменили фильтр в prepare.py.


    

Алгоритм

  1. Посмотреть, какие файлы в конфликте
    git status
  2. Открыть файл, выбрать нужное, удалить маркеры <<<<<<<, =======, >>>>>>>. В VS Code и PyCharm для этого есть кнопки и трехпанельный редактор.
  3. Убедиться, что код работает — запустить тесты или скрипт.
  4. Отметить как решенный и завершить
    git add prepare.py
    git commit                 # при merge
    git rebase --continue      # при rebase
    
git merge --abort                       # передумал: вернуть все как было до merge
git rebase --abort                      # то же для rebase
git checkout --ours   path/to/file      # взять файл целиком из «моей» стороны
git checkout --theirs path/to/file      # взять файл целиком из входящей
git diff --name-only --diff-filter=U    # список файлов с конфликтами
git config --global rerere.enabled true # запоминать решения повторяющихся конфликтов
Ловушка: ours/theirs при rebase меняются местамиПри merge «ours» — ветка, в которой вы стоите. При rebase «ours» — ветка, на которую переносят (обычно main),
а «theirs» — ваши собственные коммиты.

Как конфликтовать реже

Короткие ветки

Ветка на день-два почти не расходится с main. Ветка на месяц — гарантированная боль.

Чаще подтягивать main

git fetch && git rebase origin/main раз в день: мелкие конфликты вместо одного огромного.

Ноутбуки без выводов

Выводы и счетчики ячеек в .ipynb — главный источник конфликтов у аналитиков. Решение в следующем разделе.

08 · данные и MLGit для данных, ноутбуков и моделей

Git создан для текста. Данные, веса моделей и ноутбуки требуют нескольких дополнительных привычек.

ЧтоВ Git?Как правильно
Код, SQL, конфиги, READMEдаОбычные коммиты
Ноутбуки .ipynbда, без выводовnbstripout или jupytext
Маленькие справочники и примеры данных (до ~1 МБ)можноdata/sample/
Сырые данные, выгрузки, parquetнет.gitignore + DVC или объектное хранилище
Веса моделей, чекпойнтынетDVC, Git LFS, реестр моделей (MLflow и др.)
Пароли, токены, .envникогда.gitignore + .env.example без значений
Окружение (.venv, node_modules)нетВ Git — только файл зависимостей и lock-файл

Генератор .gitignore

Отметьте, что есть в проекте, и скопируйте результат в файл .gitignore в корне репозитория.


  
Файл уже в репозитории, а должен игнорироваться.gitignore действует только на неотслеживаемые файлы. Сначала git rm --cached путь (файл на диске останется), потом коммит. Почему файл игнорируется: git check-ignore -v путь.

Jupyter-ноутбуки аналитикуML

Ноутбук — это JSON с кодом, выводами, картинками в base64 и счетчиками выполнения. Перезапустили ячейку — получили «изменение» на сотни строк. Три инструмента, от простого к мощному:

# 1. nbstripout — автоматически вырезает выводы при коммите (файл на диске не трогает)
pip install nbstripout
nbstripout --install --attributes .gitattributes   # в корне репо, один раз
git add .gitattributes

# 2. nbdime — человеческий diff и merge для ноутбуков
pip install nbdime
nbdime config-git --enable --global
nbdiff-web old.ipynb new.ipynb

# 3. jupytext — пара .ipynb + .py; в Git кладем .py, он отлично диффится и ревьюится
pip install jupytext
jupytext --set-formats ipynb,py:percent notebooks/01_eda.ipynb
ПривычкаИсследование — в ноутбуке, переиспользуемые функции — в src/. Ноутбук импортирует код, а не содержит его целиком: меньше конфликтов, проще тестировать.

Большие файлы: DVC и Git LFS MLаналитику

DVC

В Git лежит маленький файл-указатель .dvc с хешем, сами данные — в S3, MinIO, на сетевом диске. Умеет пайплайны и воспроизведение экспериментов. Выбор по умолчанию для датасетов и моделей.

Git LFS

Прозрачно подменяет большие файлы указателями, хранит их на сервере Git. Проще в настройке, но ограничен квотами хостинга. Хорош для немногих бинарных файлов.

# DVC: версионировать папку с данными
pip install dvc dvc-s3
dvc init
dvc remote add -d storage s3://my-bucket/dvc
dvc add data/raw                       # создаст data/raw.dvc и допишет data/.gitignore
git add data/raw.dvc data/.gitignore .dvc/config
git commit -m "data: добавил сырые логи за сентябрь"
dvc push                               # данные → в хранилище

# У коллеги или на сервере обучения:
git pull && dvc pull

# Git LFS: отслеживать веса
git lfs install
git lfs track "*.pkl" "*.joblib"
git add .gitattributes

Воспроизводимость: какой код дал этот результат MLаналитику

Записывайте хеш коммита рядом с каждым результатом: в лог эксперимента, в имя файла отчета, в метаданные модели. Флаг dirty честно скажет, были ли незакоммиченные правки.

git rev-parse --short HEAD               # короткий хеш текущего коммита
git describe --tags --always --dirty     # v1.2.0-3-ga1b2c3d-dirty
git tag -a model-v1.2.0 -m "прогноз сроков согласования, AUC=0.91" && git push origin model-v1.2.0
import subprocess

def git_state() -> dict:
    run = lambda *a: subprocess.check_output(["git", *a], text=True).strip()
    return {
        "commit": run("rev-parse", "HEAD"),
        "branch": run("rev-parse", "--abbrev-ref", "HEAD"),
        "dirty": bool(run("status", "--porcelain")),
    }

# mlflow.set_tags(git_state())  или  wandb.config.update(git_state())
Эксперименты: ветки или конфиги?Меняется код (набор признаков, логика препроцессинга) — ветка exp/…. Меняются только параметры модели — это конфиг и трекер экспериментов, а не двадцать веток. Несколько экспериментов одновременно без переключений — git worktree.

Секреты и автоматические проверки

# .pre-commit-config.yaml — проверки запускаются сами перед каждым коммитом
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: check-added-large-files     # не пропустит случайный файл больше 1 МБ
        args: [--maxkb=1000]
      - id: detect-private-key
      - id: end-of-file-fixer
      - id: trailing-whitespace
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.9
    hooks:
      - id: ruff
      - id: ruff-format
  - repo: https://github.com/kynan/nbstripout
    rev: 0.7.1
    hooks:
      - id: nbstripout
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.20.0
    hooks:
      - id: gitleaks                    # ищет токены и пароли
pip install pre-commit
pre-commit install          # включить в этом репозитории
pre-commit autoupdate       # подтянуть актуальные версии хуков
pre-commit run --all-files  # прогнать по всему проекту
Секрет попал в коммитСначала отзовите и перевыпустите ключ: все, что побывало на сервере, считается скомпрометированным. И только потом чистите историю (см. мастер в разделе Отмена).

Структура проекта, с которой удобно жить

project/
├── data/              # в .gitignore или под DVC
│   └── sample/        # маленький пример — в Git
├── notebooks/         # 01_eda.ipynb, 02_features.ipynb — без выводов
├── src/               # функции, пайплайны, обучение
├── sql/               # запросы как файлы .sql, а не строки в ноутбуке
├── configs/           # параметры экспериментов (yaml)
├── models/            # в .gitignore / DVC / LFS
├── reports/           # итоговые графики и отчеты
├── tests/
├── .gitignore
├── .pre-commit-config.yaml
├── pyproject.toml     # зависимости + lock-файл (uv.lock / poetry.lock) — в Git
└── README.md          # как запустить за 5 минут

09 · командаРабота в команде

Модель ветвления

GitHub Flow по умолчанию

main всегда рабочий. Каждая задача — короткая ветка → PR → ревью → merge. Подходит большинству аналитических и ML-команд.

Trunk-based dev

Очень короткие ветки (часы), частые слияния в main, незаконченное прячется за feature-флагами. Требует хороших тестов и CI.

Git Flow

develop, release/*, hotfix/*. Оправдан для продуктов с версионными релизами. Для аналитики обычно избыточен.

Имена веток и сообщения коммитов

# Ветки: тип/краткое-описание (можно с номером задачи)
feature/DT-142-layer-heatmap
fix/duplicate-users-in-join
exp/gradient-boosting-features
docs/readme-setup

# Коммиты (Conventional Commits): тип(область): что сделано
feat(eda): добавил анализ активности по группам меню
fix(etl): исправил часовой пояс при парсинге логов
refactor(etl): вынес очистку логов в отдельный модуль
data: обновил справочник слоев (версия от 01.10)
docs: описал запуск пайплайна в README
chore: обновил зависимости

Pull / Merge request без страданий

Маленький

До 300–400 строк изменений. Большой PR никто не читает внимательно — его просто одобряют.

С описанием

Что сделано, зачем, как проверить. Для аналитики — ключевой график или цифра «до/после».

Самопроверка

Перед запросом ревью пролистайте diff сами: git diff main...HEAD. Половина замечаний находится здесь.

Защита main

Запрет прямого push, обязательное ревью и зеленый CI настраиваются в GitHub/GitLab за пару минут.

Способ слияния PR

КнопкаРезультат в mainКогда
Merge commitВсе коммиты ветки + коммит слиянияВажна подробная история ветки
Squash and mergeОдин коммит на весь PRВ ветке много «wip» и «fix typo»; самый чистый main
Rebase and mergeКоммиты ветки линейно, без коммита слиянияКоммиты в ветке аккуратные и осмысленные

10 · продвинутоеИнструменты, которые экономят часы

stash — отложить незаконченное

Срочно нужно переключиться, а коммитить рано.

git stash push -u -m "wip: heatmap"   # спрятать правки (-u — вместе с новыми файлами)
git stash list
git stash pop                         # вернуть последнее и удалить из stash
git stash apply stash@{1}             # вернуть конкретное, оставив в stash
git stash show -p stash@{0}           # посмотреть содержимое
git stash drop stash@{0}              # удалить

cherry-pick — забрать один коммит из другой ветки

git cherry-pick a1b2c3d               # скопировать коммит в текущую ветку
git cherry-pick a1b2c3d..f4e5d6c      # диапазон (не включая первый)
git cherry-pick --abort

rebase -i — навести порядок перед PR dev

git rebase -i HEAD~4                  # переписать последние 4 коммита
# В открывшемся списке замените pick на:
#   reword — изменить сообщение       squash — склеить с предыдущим
#   fixup  — склеить, сообщение выкинуть      drop — удалить коммит
#   edit   — остановиться и поправить; порядок строк = порядок коммитов

git commit --fixup a1b2c3d            # «это исправление к коммиту a1b2c3d»
git rebase -i --autosquash main       # fixup-коммиты сами встанут на место

bisect — найти коммит, который все сломал MLdev

Двоичный поиск по истории: 1000 коммитов проверяются за 10 шагов. Незаменим, когда метрика просела, отчет перестал сходиться или тест упал «непонятно когда».

git bisect start
git bisect bad                        # сейчас сломано
git bisect good v1.4.0                # здесь точно работало
# Git переключает на середину → проверяете → git bisect good / bad → повторить
git bisect run pytest tests/test_metrics.py   # или полностью автоматически
git bisect reset                      # вернуться обратно

Поиск по истории

git log -S "drop_duplicates" --oneline       # коммиты, где строка появилась или исчезла
git log -G "threshold\s*=\s*0\.\d+" --oneline # то же по регулярному выражению
git log --grep "часовой пояс"                # поиск по сообщениям коммитов
git log --author "Иван" --since "2 weeks ago"
git log --follow -p -- src/old_name.py       # история файла сквозь переименования
git grep -n "TODO"                           # быстрый поиск по текущим файлам репо
git show a1b2c3d:src/metrics.py              # файл, каким он был в том коммите
git diff main...feature/x --stat             # что изменила ветка относительно main

worktree — две ветки одновременно в разных папках ML

В одной ветке идет долгий расчет или обучение модели, а править код нужно в другой. Не надо ни клонировать заново, ни делать stash.

git worktree add ../project-exp2 -b exp/augment-v2   # новая папка с новой веткой
git worktree list
git worktree remove ../project-exp2

Большие репозитории

git clone --depth 1 URL                 # только последний снимок, без истории
git clone --filter=blob:none URL        # история есть, файлы докачиваются по требованию
git sparse-checkout set src configs     # держать на диске только нужные папки
git count-objects -vH                   # сколько весит репозиторий

Теги и алиасы

git tag -a v1.2.0 -m "Релиз отчета за Q3"
git push origin v1.2.0                  # теги сами не отправляются
git tag -l "v1.*"

git config --global alias.st "status -sb"
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.last "log -1 HEAD --stat"
git config --global alias.undo "reset --soft HEAD~1"

Чистка

git clean -nd          # показать, какие неотслеживаемые файлы будут удалены
git clean -fd          # удалить их (необратимо!)
git branch --merged main | grep -v main | xargs git branch -d   # удалить слитые ветки

11 · шпаргалкаВсе команды в одном месте

Клик по строке копирует команду. Фильтр понимает русские слова: «отменить», «удалить», «история».

12 · словарьТермины за минуту

commit
Снимок проекта с автором, датой, сообщением и ссылкой на родителя.
hash (SHA)
Уникальный идентификатор коммита, например a1b2c3d. Достаточно первых 7 символов.
branch
Именованный указатель на коммит, который сдвигается при новых коммитах.
HEAD
Указатель «я здесь». Обычно смотрит на ветку. HEAD~1 — предыдущий коммит.
detached HEAD
HEAD смотрит прямо на коммит, а не на ветку. Новые коммиты не привязаны к ветке — создайте ее через git switch -c.
index / staging
Область подготовки следующего коммита.
origin
Стандартное имя удаленного репозитория, с которого сделан clone.
origin/main
Remote-tracking ветка: локальная копия состояния main на сервере на момент последнего fetch.
upstream
Ветка на сервере, с которой связана локальная. В fork-модели — еще и имя оригинального репозитория.
fast-forward
Слияние без merge-коммита: указатель просто переезжает вперед, потому что истории не расходились.
PR / MR
Pull request (GitHub) или merge request (GitLab): предложение влить ветку с обсуждением и ревью.
tag
Неподвижная метка на коммите: версия релиза, модели, отчета.
stash
«Полка» для временно отложенных незакоммиченных правок.
reflog
Локальный журнал перемещений HEAD. Главный инструмент спасения.
merge
Слияние: соединить две линии истории. Если они расходились — появляется коммит слияния с двумя родителями.
rebase
Перенос своих коммитов поверх другой ветки. История становится линейной, но коммиты получают новые хеши.
conflict
Две ветки изменили одни и те же строки. Git останавливается и просит человека выбрать правильную версию.
cherry-pick
Скопировать один конкретный коммит в текущую ветку.
.gitignore
Список файлов и папок, которые Git не должен замечать: данные, окружение, секреты.
remote
Удаленный репозиторий — общая копия на сервере. У одного проекта их может быть несколько (origin, upstream).

Справка по любой команде: git help <команда> или git <команда> -h для краткой версии.