🌿 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.