🌿 Git

Полный справочник: настройка, коммиты, ветки, merge и rebase, конфликты, отмена и восстановление, stash, теги, удалённые, история и поиск багов, хуки, worktree, типичные workflow и спасательные рецепты.

Шпаргалки · Инфраструктура · #git #vcs #github #gitlab

Как это устроено

Четыре зоны: рабочая папка → git add → индекс (stage) → git commit → локальный репозиторий → git push → удалённый. Коммит это снимок проекта с автором, датой, сообщением и ссылкой на родителя; ветка и тег это указатели на коммиты; HEAD указывает на текущий.

Настройка

git config --global user.name "Имя Фамилия"
git config --global user.email "me@example.com"
git config --global init.defaultBranch main
git config --global pull.rebase true               # pull = fetch + rebase
git config --global fetch.prune true
git config --global rebase.autoStash true
git config --global core.autocrlf input            # Windows: true
git config --global core.editor "code --wait"
git config --global rerere.enabled true            # запоминать разрешение конфликтов
git config --list --show-origin
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.st "status -sb"

Уровни: --system, --global (~/.gitconfig), локальный (.git/config). SSH-ключ для GitHub: ssh-keygen -t ed25519 -C "me@x.com", публичный ~/.ssh/id_ed25519.pub добавить в профиль, проверка ssh -T git@github.com.

Начало работы

git init                                   # новый репозиторий
git clone <url> [папка]                    # клонировать
git clone --depth 1 <url>                  # только последний коммит (быстро)
git clone --branch dev --single-branch <url>
git remote -v / add origin <url> / set-url origin <url> / remove origin

Ежедневный цикл

git status -sb                  # коротко, что изменилось
git diff                        # неиндексированные правки
git diff --staged               # подготовленные
git add file.txt                git add -p            # выбрать куски (hunks)
git add .                       git add -u            # все в папке / только отслеживаемые
git commit -m "feat: добавить вход"
git commit -am "fix: опечатка"  # add + commit для отслеживаемых
git commit --amend --no-edit    # дополнить последний коммит (только до push)
git commit --amend -m "новое сообщение"
git restore --staged file       # убрать из индекса
git restore file                # отбросить правки в файле
git rm file / git rm --cached file       # удалить / перестать отслеживать (файл останется)
git mv old new

Сообщения коммитов (Conventional Commits)

feat: (функция), fix: (исправление), docs:, style:, refactor:, perf:, test:, build:, ci:, chore:, revert:; feat!: или BREAKING CHANGE: ломает совместимость. Первая строка до ~72 символов в повелительном наклонении, через пустую строку подробности: «что и зачем».

Просмотр истории

git log --oneline --graph --decorate --all
git log -p file.txt             git log --stat           git log -n 5
git log --author="Аня" --since="2 weeks ago" --grep="fix"
git log -S"функция" -p          # когда добавили или убрали строку (pickaxe)
git log main..feature           # что есть в feature и нет в main
git log --follow file           # история с учётом переименований
git show <sha>[:path]           git show HEAD~2
git blame -L 10,20 file         # кто менял строки
git shortlog -sn                # коммиты по авторам
git diff main...feature         # изменения ветки относительно общей базы

Ссылки на коммиты: HEAD, HEAD~1 (родитель), HEAD^2 (второй родитель merge), main@{yesterday}, abc1234, v1.0.

Ветки

git branch                      # локальные       git branch -a   # все      git branch -vv   # с отслеживанием
git switch -c feature/login     # создать и перейти
git switch main                 git switch -          # предыдущая ветка
git branch -m new-name          git branch -d feature # удалить слитую   -D — принудительно
git push origin --delete feature
git switch -c fix origin/fix    # отслеживать удалённую
git branch --merged / --no-merged
git branch -u origin/main       # привязать к удалённой

Слияние и перебазирование

git merge feature               # слить в текущую (создаст merge-коммит)
git merge --no-ff feature       # всегда создавать merge-коммит
git merge --squash feature      # собрать все изменения в один коммит
git merge --abort
git rebase main                 # переложить ветку поверх main (линейная история)
git rebase --continue / --skip / --abort
git rebase -i HEAD~5            # интерактивно: pick, reword, edit, squash, fixup, drop
git pull --rebase               git rebase --onto main old-base feature
git cherry-pick <sha>           git cherry-pick -x A..B
merge rebase
История сохраняет как была, есть merge-коммиты линейная, коммиты переписываются
Безопасность безопасно для общих веток не переписывайте опубликованные коммиты
Когда слияние фичи в main, общие ветки обновить свою ветку, почистить перед PR

Конфликты

git status                       # список конфликтных файлов
# в файле: <<<<<<< HEAD (ваше)  =======  >>>>>>> feature (чужое); отредактируйте, удалив маркеры
git add file && git merge --continue        # или git rebase --continue / git commit
git checkout --ours file / --theirs file    # взять одну сторону целиком (при rebase стороны меняются местами)
git mergetool                   git diff --check

Отмена и восстановление

Ситуация Команда
Отбросить правки файла git restore file
Убрать из индекса git restore --staged file
Переделать последний коммит git commit --amend
Отменить коммит новым (безопасно для общих веток) git revert <sha>
Отменить merge-коммит git revert -m 1 <merge-sha>
Сдвинуть ветку назад, оставив правки в индексе git reset --soft HEAD~1
Сдвинуть назад, оставив правки в папке git reset --mixed HEAD~1 (по умолчанию)
Сдвинуть назад и удалить правки git reset --hard HEAD~1
Удалить неотслеживаемые файлы git clean -fd (сначала -n посмотреть)
Вернуть «потерянное» после reset / удаления ветки git reflog, затем git switch -c rescue <sha>
Файл из другой ветки или коммита git restore --source=<sha> file
Откатить до состояния удалённой git reset --hard origin/main

reflog хранит перемещения HEAD около 90 дней: почти всё можно вернуть.

Stash (временное хранилище)

git stash push -m "wip" [-u]    # -u: с неотслеживаемыми файлами
git stash list                  git stash show -p stash@{0}
git stash pop                   git stash apply        # pop удаляет запись, apply оставляет
git stash drop stash@{0}        git stash branch new-branch stash@{0}

Теги и релизы

git tag v1.2.0                           # лёгкий
git tag -a v1.2.0 -m "Релиз 1.2.0"       # аннотированный (с автором и сообщением)
git tag -l "v1.*"                        git push origin v1.2.0 / git push --tags
git tag -d v1.2.0                        git push origin :refs/tags/v1.2.0
git describe --tags

Семантическое версионирование: MAJOR.MINOR.PATCH.

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

git fetch [--all] [--prune]      # скачать без слияния
git pull                         # fetch + merge (или rebase)
git push [-u origin branch]      git push --force-with-lease     # безопасная замена истории
git remote prune origin          git ls-remote origin
git remote add upstream <url-оригинала>; git fetch upstream; git rebase upstream/main     # форк

Не используйте git push --force в общих ветках: --force-with-lease не затрёт чужие коммиты.

Поиск ошибок

git bisect start; git bisect bad; git bisect good v1.0       # бинарный поиск плохого коммита
git bisect run npm test                                       # автоматически
git bisect reset
git grep "TODO" [-n] [ветка]

Подмодули, worktree, sparse

git submodule add <url> libs/x    git submodule update --init --recursive    git clone --recurse-submodules <url>
git worktree add ../hotfix hotfix-branch                      # вторая рабочая папка без клонирования
git sparse-checkout set src/app                               # только нужные каталоги
git lfs install; git lfs track "*.psd"                         # большие файлы

.gitignore

node_modules/
dist/
.env
*.log
.DS_Store
!important.log          # исключение из правила
/build                  # только в корне

Файл уже отслеживается? git rm -r --cached . затем git add .. Глобальный игнор: core.excludesFile. Секреты в .env.example вместо .env.

Хуки и автоматизация

Каталог .git/hooks/ (pre-commit, commit-msg, pre-push). Для команды: Husky, lefthook, pre-commit. Типично: линтер, форматирование, тесты, проверка сообщения коммита (commitlint).

Рабочие процессы

Процесс Суть
GitHub Flow main всегда готова; фича-ветка → pull request → ревью → слияние → деплой
Trunk-based короткие ветки или коммиты прямо в main, фича-флаги
Git Flow main, develop, feature/*, release/*, hotfix/* (тяжёлый, для версионных релизов)
Форк чужой репозиторий: форк → ветка → PR в оригинал

GitHub CLI: gh pr create --fill, gh pr checkout 123, gh pr merge --squash, gh issue list, gh repo clone owner/repo.

Секреты попали в историю

Токен нужно немедленно отозвать (удаления из истории недостаточно). Затем очистка: git filter-repo --path secrets.txt --invert-paths (или BFG), принудительный push, повторное клонирование командой.

Частые ситуации

# закоммитил не в ту ветку
git switch -c right-branch && git switch - && git reset --hard HEAD~1
# изменить автора последнего коммита
git commit --amend --reset-author --no-edit
# переименовать ветку с push
git branch -m old new && git push -u origin new && git push origin --delete old
# вернуть удалённый файл
git restore --source=HEAD~1 -- path/file
# сравнить файл между ветками
git diff main feature -- path/file
# сжать последние 3 коммита
git rebase -i HEAD~3   # fixup для двух последних

Внимание: reset --hard, clean -fd и push --force необратимы для незакоммиченных правок и чужой работы. Сначала git status, git stash, или создайте резервную ветку: git branch backup.