← Весь справочник

git

Система контроля версий — коммиты, ветки, слияние и rebase, откат изменений, stash, удалённые репозитории

git хранит историю проекта как цепочку коммитов — снимков файлов. Изменения проходят три места: рабочий каталог (файлы на диске), индекс (то, что войдёт в следующий коммит) и сам репозиторий (сделанные коммиты).

Синтаксис

git <команда> [опции] [аргументы]

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

Как сослаться на коммит: хэш (a1b2c3d, хватает 7 символов), ветка (main), тег (v1.0), HEAD — текущий коммит, HEAD~1 — его родитель, HEAD~3 — три коммита назад. main..feature — коммиты, которые есть в feature, но нет в main.

Команды

Настройка

КомандаЧто делает
git config user.name 'Имя' / user.emailавтор коммитов в этом репозитории; --global — для всех
git config --global init.defaultBranch mainимя первой ветки для новых репозиториев
git config --global alias.lg 'log --oneline --graph --all'своя короткая команда: git lg
git config --list --show-originвсе настройки и файлы, откуда они взялись

Создание и состояние

КомандаЧто делает
git init [каталог]создать репозиторий (появится .git/)
git clone URL [каталог]скопировать удалённый репозиторий
git status / -sчто изменено, что в индексе, что не отслеживается; -s — коротко
git add файл… / git add -Aположить изменения в индекс / все изменения, включая новые и удалённые файлы
git add -pвыбрать для индекса отдельные куски изменений
git rm файл / git rm --cached файлудалить файл / перестать отслеживать, оставив на диске
git mv старое новоепереименовать файл
git commit -m 'текст'записать индекс как новый коммит
git commit -am 'текст'сначала добавить в индекс изменения отслеживаемых файлов
git commit --amendпеределать последний коммит (текст и/или содержимое)

Просмотр истории и изменений

КомандаЧто делает
git log --onelineистория по одной строке
git log --graph --allс ветками в виде графа
git log -n 5, --since='2 weeks ago', --author=имяограничить вывод
git log -p / --statс изменениями / со списком файлов
git log -- путьтолько коммиты, менявшие файл
git log -S 'текст'коммиты, где строка появилась или исчезла
git log --format='%h %an %s'свой формат: хэш, автор, тема
git diffрабочий каталог против индекса
git diff --stagedиндекс против последнего коммита (что уйдёт в коммит)
git diff A B / --name-only / --statразница между коммитами / только имена файлов / сводка
git show коммит / git show коммит:путьизменения коммита / файл в том виде, как он был в коммите
git blame файлкто и в каком коммите менял каждую строку
git reflogкуда указывал HEAD — спасение «потерянных» коммитов

Ветки

КомандаЧто делает
git branch / -a / -vлокальные ветки / вместе с удалёнными / с последним коммитом
git branch имясоздать ветку, не переключаясь
git branch -d имя / -D имяудалить слитую ветку / удалить принудительно
git branch -m старое новоепереименовать
git branch --show-currentимя текущей ветки
git switch ветка / git switch -c веткаперейти / создать и перейти
git switch -вернуться на предыдущую ветку
git switch --detach коммитпосмотреть старый коммит без ветки
git checkout веткастарый способ переключения (умеет и switch, и restore)

Объединение

КомандаЧто делает
git merge веткавлить ветку в текущую (fast-forward, если возможно)
git merge --no-ff веткавсегда создавать коммит слияния
git merge --squash веткасобрать изменения ветки в индекс одним будущим коммитом
git rebase веткапереписать коммиты текущей ветки поверх указанной
git rebase -i HEAD~3интерактивно править последние коммиты (открывает редактор)
git cherry-pick коммитперенести один коммит в текущую ветку
--continue / --abortу merge, rebase, cherry-pick: продолжить после конфликта / отменить

Отмена изменений

КомандаЧто делает
git restore файлвернуть файл к состоянию индекса (выбросить правки)
git restore --staged файлубрать файл из индекса, правки остаются на диске
git restore --source=коммит файлвзять версию файла из коммита
git reset --soft HEAD~1отменить коммит, изменения остаются в индексе
git reset HEAD~1 (--mixed)отменить коммит, изменения остаются в файлах, но не в индексе
git reset --hard [коммит]сдвинуть ветку и выбросить все незакоммиченные изменения
git revert коммитновый коммит, отменяющий указанный (история не переписывается)
git clean -n / -fdпоказать / удалить неотслеживаемые файлы и каталоги

Stash и теги

КомандаЧто делает
git stash / git stash push -m 'текст'спрятать незакоммиченные правки
git stash -uвместе с неотслеживаемыми файлами
git stash list / show -pсписок / содержимое последнего
git stash pop / apply / dropвернуть и удалить / вернуть и оставить / удалить
git tag v1.0 / git tag -a v1.0 -m 'текст'лёгкий / аннотированный тег
git describe --tagsближайший тег для текущего коммита

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

КомандаЧто делает
git remote -v / git remote add origin URLсписок / добавить удалённый репозиторий
git fetchскачать новые коммиты, не меняя свои ветки
git pullfetch + слияние в текущую ветку (--rebase — через rebase)
git push -u origin веткаотправить ветку и запомнить связь; дальше — просто git push
git push --tagsотправить теги

Файлы, которые git должен игнорировать, перечисляют в .gitignore шаблонами (*.log, build/). Почему файл игнорируется — git check-ignore -v файл.

Примеры

# представиться (для текущего репозитория; --global — для всех)
git config user.name 'Ivan Petrov'
git config user.email 'ivan@example.com'

# новый репозиторий и первый коммит
git init
git add README.md
git commit -m 'Add README'

# что поменялось и что уйдёт в коммит
git status --short
git diff
git diff --staged

# работа в отдельной ветке и слияние обратно
git switch -c feature
git commit -am 'Fix typo'
git switch -
git merge feature

# переписать свою ветку поверх свежей основной
git switch feature
git rebase main

# история с ветками; что есть в feature и ещё нет в main
git log --oneline --graph --all
git log --oneline main..feature

# временно убрать правки, переключиться, вернуть
git stash
git stash list
git stash pop

# передумать: убрать из индекса, затем выбросить правки в файле
git restore --staged config.ini
git restore config.ini

# поправить текст последнего (ещё не отправленного) коммита
git commit --amend -m 'Better message'

# отменить опубликованный коммит безопасно — новым коммитом
git revert --no-edit HEAD

Подводные камни

  • Имя ветки по умолчанию зависит от настроек. git init в этой версии создаёт master, если не задан init.defaultBranch. Проверяй git branch --show-current, прежде чем писать main в командах.
  • Не задан user.name/user.email — git либо откажется коммитить, либо подставит что-то вроде root@hostname и выведет предупреждение. Такой автор останется в истории.
  • git diff без флагов не видит того, что уже в индексе, и не показывает новые неотслеживаемые файлы. Для индекса — git diff --staged.
  • git commit -a не добавляет новые файлы, только изменения уже отслеживаемых. Новые сначала git add.
  • git reset --hard, git restore файл и git clean -f необратимы для незакоммиченных правок: их нет ни в одном коммите. Сомневаешься — сначала git stash. Закоммиченное после reset --hard можно найти через git reflog.
  • .gitignore не действует на уже отслеживаемые файлы. Сначала git rm --cached файл, потом коммит.
  • git clean не трогает игнорируемые файлы — для них нужен ещё -x. Всегда начинай с -n.
  • git stash по умолчанию не трогает неотслеживаемые файлы. Чтобы спрятать и их, добавь -u.
  • rebase и commit --amend меняют хэши коммитов. Не переписывай ветку, которую уже забрали другие; для опубликованного используй revert.
  • git revert коммита слияния требует указать родителя: git revert -m 1 коммит.
  • git branch -d откажет для неслитой ветки (not fully merged). -D удалит её вместе с коммитами, которых больше нигде нет.
  • При конфликте git останавливается и отмечает спорные места маркерами <<<<<<<, =======, >>>>>>>. Исправь файлы, сделай git add и продолжи (--continue) или откати (--abort).
  • Первый git push новой ветки падает с has no upstream branch — нужен git push -u origin ветка.

См. также

make · ssh · gitlab-ci · github-actions