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 pull | fetch + слияние в текущую ветку (--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