Git без мистики: рабочая шпаргалка
Что такое Git на практике
Git — это распределённая система контроля версий. Слово «распределённая» важно: когда вы делаете git clone, к вам на компьютер приезжает не просто последняя версия файлов, а почти вся история проекта. Поэтому git log, git diff, переключение веток и коммиты работают локально, даже без интернета. Сервер вроде GitHub — это не «главный Git», а общий узел синхронизации, через который команда обменивается коммитами.
Git хранит проект не как папку с кнопкой «сохранить», а как цепочку снимков состояния. Каждый commit указывает на предыдущий commit, поэтому получается история: что было раньше, что изменилось потом и от какой точки выросла ветка. Внутри Git есть специальная папка .git; именно там лежит история, настройки репозитория, ссылки на ветки и служебные данные. Если удалить .git, обычные файлы останутся, но проект перестанет быть Git-репозиторием.
Полезно думать так: файлы в редакторе — это черновик, commit — осмысленная точка в истории, branch — подвижная метка на одном из коммитов, а HEAD — указатель на то место, где вы сейчас находитесь. Большая часть «магии» Git становится проще, если помнить, что команды обычно двигают эти указатели или создают новые снимки, а не делают что-то непредсказуемое с проектом.
Git нужен не для того, чтобы «сохранять файлы», а чтобы уверенно отвечать на три вопроса: что изменилось, что я хочу сохранить как осмысленный шаг и как синхронизировать этот шаг с командой. Если держать в голове эту модель, команды перестают быть набором заклинаний.
Базовая схема такая: рабочая папка — это файлы, которые вы редактируете; stage, или индекс, — черновик будущего коммита; commit — зафиксированный снимок; remote — удалённый репозиторий, например на GitHub или GitLab.
flowchart LR
A[Рабочая папка<br/>редактируете файлы] -->|git add| B[Stage / индекс<br/>черновик коммита]
B -->|git commit| C[Локальная история<br/>commit]
C -->|git push| D[Remote<br/>GitHub / GitLab]
D -->|git fetch| E[Ссылки origin/*<br/>знание о сервере]
D -->|git pull| A
E -.->|merge или rebase| AПервичная настройка
Один раз на машине задайте имя и email. Они попадут в авторство коммитов:
git config --global user.name "Ivan Petrov"
git config --global user.email "ivan@example.com"
git config --global init.defaultBranch mainПроверить настройки:
git config --listСоздать репозиторий в текущей папке:
git initСкачать существующий проект:
git clone https://github.com/user/project.gitЕжедневный цикл: status, diff, add, commit
Самая полезная команда в Git — не commit, а status. Запускайте её постоянно: перед add, перед commit, перед push, перед любым рискованным действием.
git statusПосмотреть, что именно изменено, но ещё не добавлено в stage:
git diffПосмотреть, что уже попадёт в следующий коммит:
git diff --stagedДобавить один файл:
git add src/app.jsДобавить все изменения в текущей папке:
git add .Точечно выбрать куски файла, если в нём смешались разные задачи:
git add -pСделать коммит:
git commit -m "Fix login redirect"Хорошее сообщение коммита отвечает на вопрос «что изменилось по смыслу?», а не «какие файлы тронуты?». Update files почти бесполезно. Fix empty search state уже помогает через месяц понять историю.
Ветки: безопасное место для работы
switch и checkout: почему есть две команды
В старых гайдах по Git вы часто увидите checkout вместо switch:
git checkout main
git checkout -b feature/search-empty-stateЭто не ошибка. git checkout — старая универсальная команда: ей переключали ветки, создавали ветки, откатывали файлы к версии из коммита и доставали отдельные файлы из истории. Из-за этого она перегружена: одна команда делает несколько разных по смыслу вещей.
Чтобы снизить путаницу, в Git появились более явные команды: git switch для переключения веток и git restore для восстановления файлов. Поэтому в повседневной работе лучше писать так:
git switch main
git switch -c feature/search-empty-state
git restore src/app.jsПрактическое правило простое: если вы переходите между ветками — используйте switch; если возвращаете файл к старому состоянию — restore; если читаете легаси-инструкцию с checkout, мысленно уточняйте, что именно она делает. Например, git checkout main сейчас лучше заменить на git switch main, а git checkout -- src/app.js — на git restore src/app.js.
Ветка — это указатель на линию разработки. Для новой задачи обычно лучше не работать прямо в main:
git switch -c feature/search-empty-stateПосмотреть ветки:
git branchПереключиться:
git switch mainСлить готовую ветку в текущую:
git merge feature/search-empty-stateЕсли нужно подтянуть main в свою ветку аккуратной линейной историей, часто используют rebase:
git switch feature/search-empty-state
git fetch origin
git rebase origin/mainПрактическое правило: rebase удобен для своей локальной ветки; не переписывайте историю общей ветки, если другие люди уже от неё работают.
Remote: fetch, pull, push
origin — стандартное имя удалённого репозитория. Проверить remote:
git remote -vСкачать информацию с сервера, но не менять ваши файлы:
git fetch originСкачать и сразу применить изменения к текущей ветке:
git pullОтправить вашу ветку первый раз:
git push -u origin feature/search-empty-stateДальше обычно достаточно:
git pushЕсли Git просит pull перед push, значит на сервере есть коммиты, которых у вас нет. Не делайте push --force на автомате. Сначала git fetch, git status, затем решайте: merge, rebase или обсудить с командой.
Отмена без паники
Главное различие: вы хотите убрать изменение из stage, отменить изменение в файле или отменить уже созданный коммит?
Убрать файл из stage, но оставить правки в рабочей папке:
git restore --staged src/app.jsВыкинуть локальные незакоммиченные правки в файле:
git restore src/app.jsЭто опасно: изменения в файле пропадут. Перед запуском проверьте git diff.
Исправить последний коммит, если забыли файл или ошиблись в сообщении:
git add forgotten-file.js
git commit --amendСоздать новый коммит, который отменяет старый, безопасно для общей истории:
git revert <commit>Посмотреть журнал действий, если кажется, что «всё потерялось»:
git reflogreflog часто спасает после неудачного reset или rebase, потому что показывает, где раньше был HEAD.
Stash: временно убрать незавершённую работу
Если нужно срочно переключиться на другую ветку, а текущие правки ещё рано коммитить:
git stash push -m "wip search form"Вернуть последнюю заначку:
git stash popПосмотреть список:
git stash listНе превращайте stash в долгосрочное хранилище. Если работа важна, лучше сделать черновой коммит в отдельной ветке.
Конфликты: что делать по шагам
Конфликт — не авария, а ситуация, где Git не может сам выбрать между двумя изменениями. Откройте файлы с конфликтами и найдите маркеры:
<<<<<<< HEAD
ваша версия
=======
версия из другой ветки
>>>>>>> featureОставьте правильный итоговый текст без маркеров, затем:
git add conflicted-file.js
git status
git commitПри rebase вместо git commit обычно будет:
git rebase --continueЕсли запутались во время rebase:
git rebase --abortЧастые ошибки
Не коммитьте секреты: .env, токены, приватные ключи. Добавьте такие файлы в .gitignore до первого коммита.
Не используйте git reset --hard как «почистить проект», пока не понимаете, что именно потеряете. Сначала git status и git diff.
Не делайте огромные коммиты «за весь день». Лучше несколько небольших коммитов: один смысл — один коммит. Так проще ревьюить, откатывать и искать причину бага.
Не путайте fetch и pull: fetch только обновляет знание о сервере, pull ещё и меняет текущую ветку.
Мини-практика на 10 минут
Создайте папку git-practice, выполните git init, добавьте файл notes.md, сделайте первый коммит. Затем создайте ветку experiment, измените файл, сделайте второй коммит, вернитесь в main и слейте ветку через git merge experiment. На каждом шаге запускайте git status и один раз посмотрите историю:
git log --oneline --graph --allЗапомните короткую рабочую привычку: status -> diff -> add -> diff --staged -> commit -> push. Эта цепочка закрывает большую часть повседневной работы с Git и резко снижает шанс сделать что-то вслепую.