Git
Система контроля версий Git
Команды Git
Отображение непроиндексированных изменений - git diff
Отображение списка отличающихся файлов - git diff --name-only branch1 branch2
Отображение статуса отличающихся файлов (добавлен/удалён/модифицирован) - git diff --name-status branch1 branch2
Отображение проиндексированных изменений, входящих в следующий коммит - git diff --staged или git diff --cached
Удаление файла из индекса - git rm --cached file
Отмена изменений в файле - git checkout file
Удаление последнего локального коммита - git reset --hard HEAD~
Принудительная отправка изменений в удалённую ветку (в т.ч. после удаления локального коммита) - git push -f
Отправка всех веток в удалённый репозиторий - git push --all origin
Отправка ветки branch в удалённый репозиторий - git push origin branch
Отправка ветки branch в удалённый репозиторий, если ранее её там не существовало - git push origin branch:remotebranch
Создание новой ветки с переключением на неё - git switch -c branch
Создание новой ветки из удалённой ветки с переключением на неё - git switch -c branch origin:remotebranch
Сохранение изменений во временное хранилище (к примеру, чтобы переключиться в другую ветку) - git stash
Извлечение изменений из временного хранилища - git stash pop
Синхронизация изменений с удалённым сервером - git fetch origin
Удаление ветки на удалённом сервере - git push origin --delete remotebranch
Генерация номера сборки - git describe master
Cheat Sheet
Как конфигурировать Git
Какие настройки git config сейчас следует устанавливать по умолчанию? Ниже рассмотрены избранные настройки, менять которые не стесняются даже разработчики самого Git.
Несколько недель назад я написал о настройке Git help.autocorrect и поведал странную историю о том, как её значение стали задавать в децисекундах.
Эта статья заставила меня поразмыслить и о других настройках git config, вероятно, не известных широкому кругу пользователей. Возможно, для этих настроек стоит задать по умолчанию иные значения, чем действуют сейчас.
В этом посте я разберу некоторые (пожалуй, малопонятные) настройки Git, которые сам активировал во всех моих проектах. Я подробно расскажу о них, поясню, как они действуют, и почему их, пожалуй, стоит выставить по умолчанию.
Также оказалось, что большинство из изложенных здесь знаний я почерпнул из общения с людьми, чей повседневный труд заключается в поддержке основной базы кода Git.
TLDR
Начнём с вопроса, который, возможно, не особо занимал кого-то из вас, а именно с чудесной и печальной истории значений rerere или ей подобных. Возможно, кого-то из вас посещает мысль «просто сообщите мне настройки — и я не глядя кину их в мой файл ~/.gitconfig».
Что ж, ценю вашу честность. А теперь начинается интересное:
# Явно пойдёт на пользу git
[column]
ui = auto
[branch]
sort = -committerdate
[tag]
sort = version:refname
[init]
defaultBranch = main
[diff]
algorithm = histogram
colorMoved = plain
mnemonicPrefix = true
renames = true
[push]
default = simple
autoSetupRemote = true
followTags = true
[fetch]
prune = true
pruneTags = true
all = true
# чёрт возьми, почему бы и нет?
[help]
autocorrect = prompt
[commit]
verbose = true
[rerere]
enabled = true
autoupdate = true
[core]
excludesfile = ~/.gitignore
[rebase]
autoSquash = true
autoStash = true
updateRefs = true
# дело вкуса (раскомментируйте, если не боитесь)
[core]
# fsmonitor = true
# untrackedCache = true
[merge]
# (just 'diff3' if git version < 2.3)
# conflictstyle = zdiff3
[pull]
# rebase = true
Копипаста, друзья мои.
Как разработчики ядра Git конфигурируют свои Git-ы?
Прежде, чем углубиться в каждую из этих опций по очереди, зададимся интересным вопросом: есть ли среди разработчиков Git наши единомышленники, также считающие, что эти заданные по умолчанию значения стоит поменять?
Этот вопрос не так давно всплыл в почтовой рассылке Git. Честно говоря, о некоторых из этих настроек я сам узнал только из mailing этого треда, озаглавленного «Spring Cleaning» (Весенняя уборка), в котором Фелипе Контрерас бросил вызов команде разработчиков ядра Git. Он спросил, готовы ли те удалить все накопившиеся у них конфигурационные опции и псевдонимы и на своей шкуре попробовать, каково работать с немодифицированным Git, «из коробки».
Он предложил всем участникам рассылки внимательно взвесить, какие настройки они действительно хотят изменить, а также поделиться с сообществом своими топ-листами тех настроек, которые кажутся им наиболее важными.
Результаты оказались очень интересными: получился весьма компактный список из 9 конфигурационных настроек и 3 псевдонимов, по поводу которых все участники эксперимента более-менее сошлись как по новым желательным умолчаниям. Рассмотрим изменения, которые было предложено внести в настройки конфигурации.
merge.conflictstyle = zdiff3
rebase.autosquash = true
rebase.autostash = true
commit.verbose = true
diff.colorMoved = true
diff.algorithm = histogram
grep.patternType = perl
feature.experimental = true
branch.sort = committerdate
Со времени эксперимента прошло уже 3-4 года, но ни одна из этих настроек не пополнила список умолчаний с тех пор. Здесь интересно, что многие разработчики Git сами изрядно мучаются, когда пытаются работать с Git, не включив хотя бы несколько из этих опций.
Ещё интереснее, что большинство из вас, пожалуй, не знает, что делает любая из этих настроек.
Итак, давайте в них углубимся. Что они делают, и почему вам стоило бы почти в любой ситуации слепо довериться мне и просто включить их?
Сгруппирую эти настройки в три категории:
-
Определённо пойдёт на пользу Git
-
Чёрт возьми, почему бы и нет?
-
Дело вкуса
Что ж, приступим.
Определённо пойдёт на пользу Git
Настройки из первой группы явственно улучшают Git, если включены по умолчанию. Активировав любую из них, вы просто ничего не потеряете.
Перечисление веток
В более раннем посте я уже упоминал о «советах Git» (Git Tips) в разделе «Branch Stuff», но, поскольку эта информация была и в списке «Spring Cleaning», думаю, все согласятся: перечисление веток Git по умолчанию не должно упорядочиваться по алфавиту.
Есть две настройки, помогающие улучшить эту ситуацию: branch.sort и column.ui. Первая из них сортирует список не по алфавиту, а по свежести дат коммитов (поэтому самые интересные коммиты должны находиться в верхней части списка). Вторая выстраивает имена веток в формате столбцов так, чтобы на экране было видно больше такой информации.
git config --global column.ui auto
git config --global branch.sort -committerdate
Настройка column.ui также влияет на вывод других списковых команд (очистка, статус, тег), но в целом я полагаю, что она лучше, чем действующая по умолчанию сейчас.
Можно сортировать записи не только по дате коммита, но я считаю, что это определённо полезнейшая из опций.
Перечисление тегов
Затрагивая тему перечисления, остаётся только удивляться, что опция перечисления тегов по умолчанию не включена — хотя именно она нужна практически кому угодно.
Как правило, попытавшись перечислить теги в алфавитном порядке, вы получите нечто подобное:
$ git tag
nightly/0.5.100
nightly/0.5.1000
nightly/0.5.1001
nightly/0.5.101
nightly/0.5.1010
Никому не нравится, когда 0.5.101 идёт после 0.5.1000, но таков алфавитный порядок. Можно исправить ситуацию, установив следующую опцию:
git config --global tag.sort version:refname
Именно этого мы обычно и ожидаем, трактуя версии с указанием номеров через точку как серии целочисленных значений, удобных для сортировки. Поверьте, просто нужно взять и активировать это.
Ветка по умолчанию
Этот пример, возможно, чуть более противоречив, поскольку во многом обусловлен сложившимися привычками. Но в Git лучше предусмотреть для ветки определённое имя по умолчанию, на которое система не будет ругаться всякий раз, когда вы создаёте новый репозиторий при помощи init.
git config --global init.defaultBranch main
Лично меня вполне устраивает master, и я использую такое имя в большинстве из моих репозиториев по умолчанию. Но меня вполне устраивает и main. Поэтому простой выберите наиболее устраивающий вас вариант и установите его.
Мне кажется, просто тупо, что в настоящее время Git отвлекает наше внимание на это, тогда как можно было бы просто обновить значение по умолчанию. Хотелось бы, чтобы в Git в данном случае было лучше со вкусом, поэтому только и остаётся установить тот вариант, который вам самим кажется наиболее разумным. Но выбор за вами.
Улучшенная разность
На самом деле, можно написать целый пост об алгоритмах git diff, но, если коротко — по умолчанию Git использует для вычисления разности коммитов старый, быстрый и довольно надёжный «алгоритм Майерса».
Чтобы вы понимали, что такое «старый» — уточню, что этот алгоритм был впервые описан в статье, опубликованной в 1986 году, почти 40 лет назад. Если мы с вами примерно ровесники, могу напомнить, как ощущались те времена. По телевизору тогда показывали комедию «Три амиго», мультфильм «Американский хвост», а в кинотеатрах вышел первый «Горец».
В любом случае, с тех пор были достигнуты некоторые результаты (не без уступок), и вы, возможно, удивитесь, что в базовой комплектации Git встроено 4 готовых к использованию алгоритма вычисления разности: myers, minimal, patience и histogram.
Почти не сомневаюсь, что вы будете пользоваться алгоритмом histogram (инкрементная усовершенствованная версия «patience»), а не «myers», действующим по умолчанию. Можно глобально изменить этот алгоритм вот так:
git config --global diff.algorithm histogram
Вот пример простого перемещения кода с разницей в myers и histogram, позволяющий составить краткое впечатление о том, насколько умнее можно всё это организовать:
Допустим, мы сдвигаем класс css под другой подобный ему класс, немного его изменяем, а затем выполняем команду git diff при помощи алгоритма myers, заданного по умолчанию. Получим нечто подобное:
Да, немного запутанно. Вот что в таком же сценарии нам дал бы histogram:
Теперь становится немного яснее, что именно здесь произошло.
Не далее, чем в прошлом году Элия (из нашей команды Git Merge) предположил, что
histogram или patience лучше подошли бы в качестве вариантов по умолчанию. Фелипе, написавший «Spring Cleaning», в целом предлагал то же самое, но в реальности маловероятно в какой-либо обозримой перспективе этот вызов будет принят.
Здесь много материала, но можно внести в git diff и некоторые более мелкие корректировки:
git config --global diff.colorMoved plain
git config --global diff.mnemonicPrefix true
git config --global diff.renames true
Вариант colorMoved также был в списке предложений из «Spring Cleaning», поэтому данное изменение также, пожалуй, следует внести по умолчанию.
Рассмотрим предыдущий пример с переносом кода при включённой опции colorMoved:
Вы видите, чем отличается перемещённый код и добавленная строка. При включённой опции colorMoved перемещение кода будет отображаться разными цветами, в зависимости от того, были какие-то строки добавлены или удалены.
Опция diff.renames позволяет выявить, был ли файл переименован, и обычно это хорошо (пусть и немного затратно), а diff.mnemonicPrefix заменяет a/ и b/ в выведенном заголовке разности фрагментов на информацию о том, откуда пришло различие, вот так: i/ (индекс), w/ (рабочий каталог) или c/ (коммит).
Таким образом, если я сравниваю изменение из моего индекса с информацией из моего рабочего каталога, то получу в качестве заголовка изменённого фрагмента следующий вывод:
❯ git diff
diff --git i/apps/web/page.js w/apps/web/page.js
index 7568be2ef..b9e9a00d7 100644
--- i/apps/web/page.js
+++ w/apps/web/page.js
Может быть, из этого примера не вполне очевидно, но по именам путей вполне можно уловить, какая часть поступила из индекса, а какая — из рабочего каталога. Разница в самом деле тонкая, но тем она мне и нравится.
Улучшаем пуш
Среди тех вещей, которые неизменно путают и напрягают меня с первых дней работы с Git — это сложности с правильной настройкой отслеживания веток. Когда я пушу код, куда пушится этот код, и пушится ли вообще?
Есть три обновлённые настройки, задавая которые по умолчанию, можно значительно повысить удобство работы с инструментом. Первая (push.default simple) назначена по умолчанию, начиная с Git 2.0, но другие по-прежнему нужно устанавливать явно.
git config --global push.default simple # (по умолчанию с версии 2.0)
git config --global push.autoSetupRemote true
git config --global push.followTags true
Этот момент всегда был в Git болевой точкой. Новое умолчание simple более или менее рассчитано на работу с централизованными потоками задач, стандартно пуш осуществляется в текущую ветку и в одноимённую ветку на удалённой машине. Я думаю, это очень разумное умолчание.
Однако, если эта ветка не существует, а отслеживание веток не настроено, то вы всё равно получите следующую ошибку:
$ git push
fatal: The current branch my-branch-name has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin my-branch-name
Вполне возможно, что следующую картинку вы видели миллион раз.
Если установить push.autoSetupRemote в true, то эту ошибку вы более получать не будете. Если вышестоящая ветка не установлена, то программа её автоматически установит. Просто не передать, как мне нравится эта настройка.
Наконец, настройка push.followTags запушит все теги, имеющиеся у вас на локальной машине, но отсутствующие на сервере. Это происходит при каждой пуш-операции. Я на этом несколько раз обжигался. Но, если вы создаёте теги на локальной машине, то активируйте эту настройку, тогда сможете не беспокоиться, что ваших тегов не увидят другие люди.
Улучшенная выборка
Можно утверждать, что было бы хорошо держать на локальной машине историю копий веток и тегов, которые когда-то были на сервере, а теперь там отсутствуют, но я с этим согласиться не могу.
Лично я считаю, что по умолчанию Git должен работать так: держать ссылки на ваш код, расположенные на локальной машине, максимально схожими на ссылки, находящиеся на удалённой машине. Отсекайте всё устаревшее, т.д.
Поэтому я поставил бы по умолчанию следующие настройки выборки:
git config --global fetch.prune true
git config --global fetch.pruneTags true
git config --global fetch.all true
На самом деле, всё это позволяет нам не сомневаться, что мы удалим origin/blah, если blah будет удалено на сервере. Причём всё это будет автоматически делаться на всех удалённых машинах, если правильно сконфигурировать такие настройки. Мне кажется, это очень разумно.
Чёрт возьми, почему бы и нет?
Настройки из следующей группы, как правило, безобидны, но могут и помочь.
Я не уверен, что здесь обязательно менять умолчания, но и не думаю, что приведённые здесь варианты кому-то повредят. В некоторых случаях они даже очень пригодятся. Поэтому включу их в мой список.
Предложения автозамены
Как я подробно объяснял в одном из моих предыдущих постов, в Git есть такая довольно приятная возможность: если случайно механически ошибётесь при наборе команды, система попробует догадаться, что вы имели в виду, и запустить именно нужную команду.
По умолчанию мы попытаемся этого избежать, а сделать наоборот: чтобы программа сама предлагала вам, что ввести.
git config --global help.autocorrect prompt
Если вы хотите подробнее почитать об этой настройке, чем она обоснована, а также какова её история, то вот дотошный пост о ней.
Коммиты с указанием разности
Это предложение содержалось в списке «Spring Cleaning» — думаю, оно попало туда в основном потому, что с его помощью можно расширить контекст и добавить информацию, с которой затем можно будет сверяться, когда будете писать в редакторе сообщения о коммитах.
По умолчанию git commit будет выдавать сообщение, которое выглядит примерно так:
Здесь мы видим только список изменившихся файлов. Если установить commit.verbose в значение true, то сюда будет записан весь вывод diff, и вы сможете сверяться с ним, когда будете писать ваше сообщение.
git config --global commit.verbose true
Вот какой вид это примет теперь, когда вы перейдёте к коммиту:
Всё это будет удалено из сообщения о коммите (всё, что расположено ниже этой забавной «линии разреза» -- >8 -- ), но зато вы получите гораздо более подробный контекст, когда будете писать сообщение.
Повторное использование ранее записанных разрешений конфликтов
Эта настройка пригодится вам лишь в случаях, когда вы выполняете перебазирование, и при этой работе раз за разом возникают конфликты. Не самая распространённая ситуация, но не будет и никаких проблем, если эту настройку просто включить и никогда не использовать.
git config --global rerere.enabled true
git config --global rerere.autoupdate true
Опция enabled гарантирует, что система будет записывать состояния «до» и «после» конфликтов при перебазировании. После этого autoupdate будет автоматически раз за разом применять проверенные разрешения конфликтов, с которыми сталкивается не в первый раз. Я достаточно подробно написал об этом здесь, поэтому не буду здесь заново утомлять вас этой темой.
Глобальный файл ignore
Эта настройка даже не простая, а тупая, но, поскольку есть файл ~/.gitconfig с глобальными значениями, было бы круто иметь и файл ~/.gitignore с глобальными значениями. Благодаря этой настройке достигается следующее:
git config --global core.excludesfile ~/.gitignore
На самом деле, в этом, мягко говоря, нет необходимости, поскольку Git и так ищет глобальные ignore-значения в двух следующих местах: ~/git/ignore и ~/.config/git/ignore. Но, поскольку они выглядят немного непонятно, полагаю, было бы хорошо проложить туда более логичный путь.
Чуть более аккуратное перебазирование
В этом разделе рассмотрим преимущественно тот практический случай, в котором вы исправляете и ужимаете ваши комментарии. Если вы не знаете, что это такое, можете почитать мой более ранний пост на тему autosquashing.
Правда, если этой работой приходится заниматься в больших масштабах (или даже время от времени), вам определённо помогут и не повредят следующие настройки.
git config --global rebase.autoSquash true
git config --global rebase.autoStash true
git config --global rebase.updateRefs true
Настройка updateRefs практически наверняка должна выставляться по умолчанию, честно. Она просто организует в виде ветки стопку ссылок и гарантирует, что при перебазировании ветки эти ссылки также будут правильно перемещены.
Дело вкуса
Следующая группа настроек зависит от ваших личных предпочтений. Но большинство не знает, что эти настройки существуют, и многим они могут оказаться полезными. В разделе TLDR выше в этой статье я их закомментировал.
Улучшенная обработка конфликтов при слиянии
Итак, хотя эта тема и затрагивается в треде «Spring Cleaning» как потенциальная новая настройка по умолчанию, я не уверен, что с этим можно согласиться.
Когда в Git возникает конфликт при слиянии веток, лучше не расставлять маркеры конфликтов слева и справа, можно попросить вставить ветку, которая выглядела бы как новая база. Иногда это бывает по-настоящему полезно, но некоторых весьма раздражает.
git config --global merge.conflictstyle zdiff3
В почтовой рассылке Git шли дискуссии о том, не активировать ли эту настройку по умолчанию. Кстати, в GitButler при работе с маркерами конфликтов используется стратегия diff3 — и, будем честны, далеко не всем она нравится.
Рассмотрим пример с установкой простого маркера при конфликте слияния, который может возникнуть в файле при слиянии или перебазировании:
Если включить настройку merge.conflictStyle zdiff3, получим:
В сущности, кроме секций <<<<<< и >>>>>>, в которых вы видите, как вы изменили блок, и как его изменил кто-то другой, здесь также добавляется блок |||||||, демонстрирующий, как выглядела ветка до вышеупомянутых изменений.
Этот дополнительный контекст (позволяющий судить, как выглядела ветка до того, как в неё были внесены изменения) иногда бывает крайне полезен, но, как правило, это всего лишь дополнительные данные, в которых можно запутаться.
На самом деле, именно от вас зависит, хотите ли вы иметь под рукой эти дополнительные данные.
Скрытый текст
Стратегия diff3 применялась в Git почти всегда. Я рекомендую здесь zdiff3, что означает "ревнивое diff3" и чуть лучше на практике, но этот вариант доступен только начиная с версии Git 2.35 (январь 2022). Если вы работаете с более старой версией Git — просто уберите "z".
Улучшенное подтягивание
Конечно, в споре о слиянии и перебазировании едва ли можно прийти к общему мнению, но, как правило, у нас есть предпочтения. Возможно, вы не знали, что, если установить git pull по умолчанию, то делаться будет только один или другой вариант. Нет необходимости в git pull --rebase, можно просто задать по умолчанию следующее:
git config --global pull.rebase true
Это только вам решать, но я лишь недавно с концами перебрался в лагерь «только перебазирование», конечно, это отразилось на той конфигурации, которой я пользуюсь.
Выполняйте процессы fsmonitor
Опять же, это актуально только для больших репозиториев, возможно, вы не хотите, чтобы в вашей файловой системе повсюду шёл мониторинг. Но эти процессы могут значительно ускорить такие вещи как git status, если вам приходится иметь дело с большими рабочими каталогами.
Может быть, эту настройку и не стоит задавать по умолчанию, но она неплоха, и в определённых случаях, что называется «делает разницу». Может быть, стоит спрашивать в git clone, хотите ли вы её задействовать. В любом случае, такая опция существует.
git config --global core.fsmonitor true
git config --global core.untrackedCache true
Так будет запускаться процесс для мониторинга файловой системы (по одному на каждый репозиторий), который будет замечать изменения в файлах и обновлять кэш, так, что git status не придётся заново индексировать каждый файл тысячами статистических вызовов mtime, лишь чтобы проверить, не появились ли элементарные изменения в логах.
Подчеркну, что в данном случае запускается по одному процессу на каждый репозиторий, в котором вы работаете — может получиться немало. Обычно, правда, работают они не так активно, поскольку основаны на событиях, и поэтому они не оказывают заметной нагрузки на память или ЦП, даже если таких процессов сотни. Но стоит иметь в виду такую возможность. Также просто можете убрать опцию --global и активировать её только в больших репозиториях.
Заключение
Надеюсь, эта статья послужит вам полезной справкой. Возможно, вы узнали что-то новое о конфигурации в Git и согласитесь со мной, что хотя бы некоторые из перечисленных вещей обязательно нужно выставлять по умолчанию. По некоторым из этих вариантов даже в почтовой рассылке сообщества Git царит единогласие.
Есть и множество других способов пришпорить Git (псевдонимы, классные внешние инструменты pager и diff, другие подобные вещи), но я думаю, что вам было бы лучше всего придерживаться глобально полезных и относительно простых стандартных настроек Git.
P.S. В конфигурационный файл для соблюдения правила "1 строка = 1 запись" можно добавить:
[format]
pretty = format:%C(cyan bold)%H%C(reset) %ci %C(italic)(%cr)%C(reset) %C(blue)%cn%C(reset) %C(auto,bold)%G?(%GT)%C(reset) %C(green)%s%C(magenta)%d%C(reset) %C(red)(%an)%C(reset) %C(yellow)[%p]%C(reset)
Выглядит так:
Основные команды GIT
О чем статья
В этой статье я расскажу о том, как работает Git , какие основные команды нужно знать, как пользоваться, и как они помогают решать повседневные задачи. Даже если ты только начинаешь свой путь в программировании — здесь всё будет объяснено просто, без сложных терминов и с примерами из жизни.
Что такое GIT
Git — это распределённая система контроля версий, разработанная для отслеживания изменений в исходном коде во время разработки программного обеспечения. Она позволяет нескольким разработчикам работать над одним проектом одновременно, управлять изменениями, создавать различные ветки для экспериментов и слияний, а также легко откатывать изменения при необходимости.
Предустановка
Необходимые инструменты для работы:
-
git. Скачатьgitможно по ссылке https://git-scm.com/downloads. -
Текстовый редактор. Можете использовать любой. В моем случае
VS Code. Ссылка: https://code.visualstudio.com/download. -
Зарегистрировать аккаунт на Github и создать новый репозиторий на странице https://github.com/new. Вы можете оставить все по умолчанию, указав только название репозитория. Я же назову его
Guide. Затем выйдет страница, которая также описывает как начать пользоватьсяGit-ом. -
Два каталога (папки) для наглядной работы некоторых
git-команд (имитации командной работы). Я расположил их на рабочем столе и назвалroot— будем работать в основном в ней, иaddon— имитация командной работы.
Содержание
Первые шаги, первый push
Вторые шаги
Менее юзаемые команды
Основные команды
Вывод
Первые шаги, первый push
1. Инициализация репозитория
git init
Команда используется для создания нового репозитория Git. Она инициализирует пустой репозиторий в указанной директории, создавая все необходимые файлы и директории для работы с Git.
2. Настройки параметров конфигурации Git.
git config
Команда, используемая для настройки параметров конфигурации Git. Эти параметры могут быть настроены для текущего пользователя, всего репозитория или глобально (флаг --global) для всех репозиториев на компьютере.
При помощи следующей команды, Вы укажете имя (ТОЛЬКО для текущего репозитория), которое будет отображаться на отправленных Вами коммитами:
git config user.name "Ivan"
Если Вы хотите указать имя также и для будущих проектов, то используйте флаг --global:
git config --global user.name "Ivan"
Тоже самое можно проделать и с почтой. Она также будет отображаться в дальнейших коммитах:
git config user.email "your@gmail.com"
или глобально
git config --global user.email "your@gmail.com"
Если Вы пропустите этот пункт, не указав user.email и user.name, то на этапе использования команды git commit Вас попросят их ввести.
3. Состояние рабочего каталога и индекса
git status
Команда используется для отображения состояния рабочего каталога и индекса (staging area). Она показывает изменения, которые были добавлены в индекс и готовы для коммита, а также изменения, которые еще не были добавлены. Это помогает разработчикам отслеживать текущие изменения в проекте.
Добавим в текущий каталог файл index.html:
echo "<p>Hello Git!</p>" > index.html
Теперь можно использовать команду git status, после которой Вы увидите следующее:
git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.html
nothing added to commit but untracked files present (use "git add" to track)
Мы можем увидеть:
-
Мы находимся на ветке
master(On branch master). -
У нас до сих пор нет коммитов (No commits yet).
-
У нас имеются неотслеживаемые файлы (Untracked files).
-
Ничего не добавлено в commit, но имеются неотслеживаемые файлы (nothing added to commit but untracked files present).
Флаг -u отслеживает только Untracked files. Используется, когда необходимо увидеть только неотслеживаемые файлы и каталоги.
4. Добавление изменений в индекс
git add
Чтобы добавить файлы в индекс, мы должны указать какие именно файлы мы хотим добавить. Давайте добавим index.html:
git add index.html
Теперь можем прописать команду git status:
...
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: index.html
...
Как мы можем видеть, файл index.html добавился в индекс.
Основные команды:
-
git add index.html index.css— добавить сразу несколько файлов; -
git add . (-A)— добавить все файлы
5. Отмена изменений в репозитории
git reset
Команда используется для отмены изменений в репозитории. Она может изменять как индекс (staging area), так и рабочий каталог. git reset имеет несколько режимов, которые определяют степень отката изменений: --soft, --mixed и --hard.
-
--soft— оставляет изменения в рабочем каталоге и в индексе. Перемещает указатель текущей ветки к указанному коммиту. -
--mixed(по умолчанию) — Оставляет изменения в рабочем каталоге, но удаляет их из индекса. -
--hard— удаляет изменения из рабочего каталога и индекса, возвращая состояние файлов к указанному коммиту.Будьте аккуратны, когда используете флаг
--hard!!! -
--soft HEAD~1— откатить коммит, оставить изменения в индексе. -
git reset --keep HEAD~1: откатить, сохранив локальные изменения.
Если Вы хотите удалить какой либо файл (допустим index.js) из индекса пропишите:
git reset index.js
После чего он снова станет неотслеживаемым.
Если хотите удалить все файлы из индекса, просто пропишите git reset.
6. Сохранение изменений в локальном репозитории Git
git commit
git commit, Git сохраняет текущие изменения, добавленные в индекс (staging area), в виде коммита с уникальным идентификатором (SHA-1 хэшем), который содержит информацию о всех изменениях, авторе, времени и сообщении коммита.Создадим commit:
git commit -m "Initial commit"
Предположим, что мы забыли добавить index.css. Для начала создадим его, затем добавим его в индекс, используя команды:
echo "* { margin: 0; }" > index.css
git add index.css
git commit --amend --no-edit
Основные команды:
-
git commit --amend --no-edit— изменить коммит без изменения его сообщения. -
git commit -a -m "Обновил все изменённые файлы"— добавление всех изменённых файлов (не добавляет новые файлы) и создание коммита. -
git commit --author="Ivan <ivan@example.com>" -m "Добавил новые функции"— создание коммита с указанием автора. -
git commit --allow-empty -m "Пустой коммит"— создание пустого коммита (без изменений).
7. Просмотр истории коммитов
git log
Команда используется для просмотра истории коммитов в репозитории Git. Эта команда предоставляет информацию о каждом коммите, включая SHA-1 хэш коммита, автора, дату и сообщение коммита. С помощью различных опций можно фильтровать и форматировать вывод для более удобного анализа истории проекта.
Если мы введем данную команду, то увидим следующее:
git log
commit c136c5185822bf95b6636851cf6e67a8f732cfeb (HEAD -> master, origin/master)
Author: Ivan <ivan@gmail.com>
Date: Mon Jul 22 16:30:24 2024 +0700
Initial commit
c136c5185822bf95b6636851cf6e67a8f732cfeb является хэшом.
Основные команды:
-
git log --oneline— компактный вывод -
git log -p— просмотр коммитов с определенными изменениями -
git log -n— количество выводимых коммитов -
git log --graph— вывод изменений в виде дерева -
git log --stat— вывод статистики изменений -
git log --author="Ivan"— фильтрация коммитов по автору -
git log --since="2024-22-07"(с) и--until="2024-22-08"(до) — фильтрация коммитов по дате -
git log index.html"— показывает коммиты, затрагивающие конкретный файл -
git log --name-only"— показывает только имена изменённых файлов
8. Отправка коммитов в удаленный репозиторий
git push
Команда используется для отправки коммитов из локального репозитория в удаленный репозиторий. Эта команда обновляет удаленные рефы вместе с объектами, необходимыми для полного копирования истории изменений.
Если мы введем команду:
git push
То получим:
fatal: No configured push destination.
Either specify the URL from the command-line or configure a remote repository using
git remote add <name> <url>
and then push using the remote name
git push <name>
Вот здесь нам как раз-таки и понадобится та самая предустановка, которую мы провели в самом начале.
Вы должны будете скопировать строку с
https://github.com/<Ваш аккаунт>/<Ваш репозиторий>.git и добавить удаленный репозиторий:
git remote add origin https://github.com/<Ваш аккаунт>/<Ваш репозиторий>.git
Вместо
originможете дать свое название, но по умолчанию обычно используетсяorigin.
Если мы снова попробуем ввести команду git push, то получим:
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin master
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
Сообщение, которое вы получили, означает, что ваша текущая ветка master не связана с удаленной веткой в вашем удаленном репозитории (origin). Upstream ветка — это удаленная ветка, с которой ваша локальная ветка синхронизируется при выполнении команд git push и git pull.
Если вы хотите, чтобы Git автоматически устанавливал upstream ветку при первом пуше новой локальной ветки, вы можете настроить параметр push.autoSetupRemote. Для этого выполните команду:
git config --global push.autoSetupRemote true
Теперь перейдя по ссылке https://github.com/<Ваш аккаунт>/<Ваш репозиторий> Вы увидите следующее:
Поздравляю с Вашим первым push-ем!!!🎉🎉🎉
Основные команды:
-
git push -force(-f) — принудительно перезаписывает историю на удалённом репозитории. Осторожно! Может сломать работу других разработчиков. -
git push --force-with-lease— то же, что--force, но проверяет, не изменилась ли удалённая ветка за время твоей работы. Более безопасно -
git push --set-upstream <удаленный репозиторий> <удаленная ветка>(-u): устанавливает связь между локальной и удалённой веткой. Полезно при первом пушинге новой ветки.
Вторые шаги
9. Управление ветками
git branch
Команда используется для управления ветками в репозитории Git. С её помощью можно создавать, удалять и перечислять ветки. Ветки в Git позволяют вам изолировать работу на различных функциях, исправлениях или версиях проекта.
Так как мы имеем только одну ветку, то при выполнении данной команды увидим:
* master
Создадим новую ветку develop:
git branch develop
Основные команды:
-
git branch --delete(-d) — удаляет указанную ветку (только если она объединена с другой) -
git branch -D— принудительно удаляет ветку, даже если она не была объединена -
git branch --move(-m) — переименовывает ветку -
git branch --all(-a) — показывает все ветки: локальные и удалённые -
git branch --remotes(-r) — показывает только удалённые ветки -
git branch <name> <commit>— создаёт ветку на указанном коммите или теге
10. Переключение между ветками
git switch
Команда git switch используется для переключения между ветками.
Переключимся на ветку, которую мы только что создали:
git switch develop
Мы также могли создать ветку при помощи git switch и сразу переключиться на нее при помощи флага -c:
git switch -c develop
Добавим файл index.js:
echo "console.log('Hello')" > index.js
Добавим файлы в индекс, сделаем commit и push данной ветки:
git add .
git commit -m "First commit on develop"
git push
Теперь перейдя в удаленный репозиторий на сайт, мы увидим, что у нас появилась новая ветка.
Основные команды:
-
git switch --create <имя>(-c) — создаёт новую ветку и переключается на неё -
git switch --track(-t) — устанавливает связь с отслеживаемой удалённой веткой
11. Создание копии удаленного репозитория
git clone
Команда используется для создания копии (клонирования) удаленного репозитория на ваш локальный компьютер. Это один из наиболее распространенных способов начать работу с существующим проектом в Git. При клонировании репозитория Git создает локальную копию всех данных и истории коммитов из удаленного репозитория.
Клонируем наш репозиторий в каталог addon, который мы создали на этапе предустановки в 4 пункте. Советую открыть новое окно VS Code и уже в нем клонировать репозиторий.
git clone `https://github.com/<Ваш аккаунт>/<Ваш репозиторий>.git` .
Если мы выполним команду git branch -a, то увидим:
* master
remotes/origin/HEAD -> origin/master
remotes/origin/develop
remotes/origin/master
Нам нужно клонировать ветку:
git switch --track origin/develop
или
git checkout -b develop origin/develop
или можно было сразу
git clone -b develop https://github.com/<Ваш аккаунт>/<Ваш репозиторий>.git` .
12. Временное хранилище
git stash
Команда используется для временного сохранения (stash) изменений в рабочем каталоге, которые еще не готовы для коммита. Это полезно, когда нужно переключиться на другую ветку или работу, но текущие изменения не должны быть потеряны. С помощью git stash изменения сохраняются в специальное место, откуда их можно восстановить позже.
Отступление
Представим ситуацию:
Вы офисный работник, выполняете 3-ий день подряд Task-у с Azure (TFS)
#111 Добавление печати пропускавместе со своими коллегами и сидите на локальной веткеfeature/111_add_print, которой соответствует удаленнаяorigin/feature/111_add_print. Вы уже перелопатили половину кода, что-то в текущий момент перестало работать.Как вдруг вбегает начальник и говорит: "Мы теряем бабки!!! Бросай свои дела и быстро исправляй ошибки! Кто умудрился в
console.log()выводить пароль?".У Вас код перестал работать, а он со своими проблемами. Не пошлешь же начальника, хотя скорее всего очень хочется. Что ж, придется исправлять. Для этого нужно создать новую ветку
hotfix/change_clg, переключиться на нее и убрать эту лишнюю строку.Давайте попробуем это сделать.
-
Для начала создадим удаленную ветку
origin/feature/111_add_print. Для этого переключимся на новую веткуfeature/111_add_print, добавим немного кода вindex.jsи вindex.css, сделаем коммит и запушим:git switch -c feature/111_add_print echo "function Print(){}" >> index.js echo "p { text-align: center; }" >> index.css git add . git commit -m "Add print function" git push -
"Перелопатим" код (добавим изменения в файл
index.js):echo "const y = true;" >> index.js echo "console.log(y)" >> index.js -
Так как нам нужно исправлять код рабочий — наследоваться от ветки
develop, а не отfeature/111_add_print, то нам для начала необходимо переключиться на develop и от него создать веткуhotfix/change_clg:git switch develop error: Your local changes to the following files would be overwritten by checkout: index.js Please commit your changes or stash them before you switch branches. AbortingНо увидим ошибку, которая говорит о том, что мы сделали локальные изменения и их нужно либо запушить, либо отправить в
stash, прежде чем мы сможем переключиться. -
Для этого используем команду:
git stashЕсли мы пропишем
git status, то увидим, что наши изменения пропали. На деле они находятся вstash.Теперь мы сможем переключиться на
develop.
Основные команды:
-
git stash— отправка изменений в стэш; -
git stash push -m "Временные изменения"— Отправка изменений в стэш с указанием сообщения; -
git stash list— список сохранённых стэшей; -
git stash apply— применение последнего стэш; -
git stash pop— применение и удаление последнего стэша; -
git stash apply stash@{n}— применение конкретного стэша; -
git stash drop stash@{n}— если 0, то удаление всех стэшей, другое число — удаление определенного стэша; -
git stash clear— очистка всех стэшей.
13. Создание псевдонимов
git config alias
Данная подкоманда используется для создания псевдонимов команд, которые позволяют заменить одним словом целую строку. Псевдонимы упрощают и ускоряют выполнение часто используемых команд.
Если Вы заметили, то мы часто используем команду git commit -m "". Мы можем упростить ее написание создав для нее алиас:
git config --global alias.ctm 'commit -m'
Теперь вместо commit -m мы будем использовать ctm.
Создадим еще парочку алиасов:
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --decorate --all"
Получить список созданных алиасов можно командой:
git config --get-regexp alias
Удалить ненужный алиас (допустим ctm):
git config --global --unset alias.ctm
14. Старший брат команды git switch
git checkout
Команда используется для различных целей, таких как переключение между ветками, создание новых веток, восстановление файлов и переключение на конкретные коммиты.
Переключимся на новую ветку, унаследовавшись от последнего коммита в develop:
git log develop --oneline -1
126dadc (HEAD -> develop, origin/develop) First commit on branch develop
Во 2-ой строке получили хэш. Теперь создаем ветку на основе этого хэша:
git checkout -b hotfix/change_clg 126dadc
Изменим файл index.js на:
console.log("Вы успешно вошли")
Сделаем commit и push при помощи созданного алиаса:
git add .
git ctm "Убрал `pass` в console.log()"
git push
Основные команды:
-
git checkout <branch-name>— создание новой ветки -
git checkout -b <branch-name>— создание новой ветки и переключение на нее -
git checkout <commit-hash>— переключение на конкретный коммит -
git checkout <branch-name> <commit-hash>— создание новой ветки от определенного коммита -
git checkout -- <file-path>— восстановление файла до состояния последнего коммита -
git checkout -- .— восстановление всех файлов до состояния последнего коммита
15. Слияние изменений веток
git merge
Команда используется для слияния изменений из одной ветки в другую. Эта команда объединяет истории коммитов двух веток, создавая новый коммит (по умолчанию), который включает изменения из обеих веток.
Вольем наши изменения из ветки hotfix/change_clg в develop:
git switch develop
git merge --no-ff hotfix/change_clg -m "Слияние изменений из hotfix/change_clg в develop"
git push
Очень важно писать --no-ff, чтобы сохранить структуру разработки.
Наглядный пример работы:
Теперь на ветке develop в удаленном и локальном репозитории файлы будут обновлены.
Основные команды:
-
git merge <from-branch> --no-ff— создаёт новый коммит слияния, даже если возможно быстрое слияние (fast-forward). Полезно для сохранения истории слияния. -
git merge <from-branch> --no-commit— объединяет изменения, но не делает коммит автоматически. -
git merge <from-branch> --squash— объединяет все коммиты из сливаемой ветки в один коммит в текущей ветке. Полезно для объединения истории коммитов перед слиянием. -
git merge --continue— продолжает слияние после разрешения конфликтов -
git merge --abort— прерывает начатое слияние при возникновении конфликтов
16. Загрузка обновлений из удаленного репозитория
git fetch
Команда используется для загрузки обновлений из удаленного репозитория в ваш локальный репозиторий. В отличие от git pull, git fetch не сливает изменения автоматически в вашу текущую ветку. Вместо этого она загружает все обновления, которые затем можно просмотреть и слить вручную.
Переключимся обратно на каталог root.
Загрузим обновления из удаленного репозитория командой git fetch.
В консоли видим:
...
652b6ff..b585d2a develop -> origin/develop
* [new branch] feature/111_add_print -> origin/feature/111_add_print
* [new branch] hotfix/change_clg -> origin/hotfix/change_clg
Здесь видим краткую информацию, что develop обновился и появились две новые ветки
Пишем git log -1 --oneline и видим, что коммит не соответствует тому, что должно быть в удаленном репозитории.
Пишем git log origin/develop -1 --oneline и видим последний коммит.
Если запускать с флагом --prune, то он уберет локальные ссылки на удалённые ветки, которых уже нет на сервере.
17. Извлечение и слияние изменений
git pull
Команда используется для извлечения и слияния изменений из удалённого репозитория в вашу текущую ветку. Эта команда объединяет две операции: git fetch и git merge. Сначала она извлекает изменения из удалённого репозитория (аналогично git fetch), а затем автоматически сливает их с текущей веткой (аналогично git merge).
Выполним команду git pull и наша локальная ветка develop будет соответствовать удаленной ветке origin/develop.
Переключимся на ветку feature/111_add_print и вытянем изменения, которые мы сделали в develop:
git switch -t origin/feature/111_add_print
git merge develop
Как мы можем увидеть, у нас конфликты:
warning: Cannot merge binary files: index.js (HEAD vs. develop)
Auto-merging index.js
CONFLICT (content): Merge conflict in index.js
Automatic merge failed; fix conflicts and then commit the result.
Сам же файл:
<<<<<<< HEAD
console.log("Вы успешно вошли")
=======
console.log(pass)
function Print(){}
>>>>>>> 2c0279a (Add print function)
Вы можете отредактировать файл вручную, удалив строки <<<<<<< HEAD, =======, >>>>>>> 742b087 (Add print function) и внести нужные изменения, сохраняя только те строки, которые вы хотите оставить.
Или Вам предложат открыть Merge editor (возможно автоматически откроется), чтобы решить данный конфликт. В нем current будет ветка develop, incoming — feature/111_add_print, а result — результат слияния. Можно выбрать оба изменения, либо одно, нажав на соответствующие галочки, либо написать что-то свое и нажать на Complete Merge. Я добавлю оба изменения:
console.log("Вы успешно вошли")
function Print(){}
Если мы пропишем git status, то увидим:
git status
On branch feature/111_add_print
Your branch is up to date with 'origin/feature/111_add_print'.
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: index.js
Как видно мы в состояния merging (you are still merging), нужно завершить merge, просто пишем:
git merge --continue
18. Работа с текстовым редактором vim
У вас откроется редактор, в котором Вы можете поменять сообщение коммита. Строки начинающиеся с # считаются комментариями. По умолчанию merge создает commit: Merge branch 'develop' into feature/111_add_print. Чтобы изменить его, нужно перейти в интерактивный режим — нажмите i, выйти из режима без сохранения :q!. Чтобы сохранить изменения необходимо нажать клавишу Esc затем ввести :wq! (Посимвольно означает: Перейти в командный режим + Записать + Выйти + Принудительно выполнить).
Оставлю название commit по умолчанию. Осталось только запушить эти изменения.
git push
Переключимся на addon. Пропишем git switch feature/111_add_print, git pull. У нас подтянутся изменения — строка с console.log.
Наконец-то возвратимся к изменениям, которые сохраняли в стэш. Применим их:
git stash pop
Опять конфликты, но мы на опыте, решаем их.
Добавим изменения в индекс, закоммитим и запушим:
git add .
git ctm "Make print"
git push
Вольем наши изменения в ветку develop и запушим:
git switch develop
git merge --no-ff feature/111_add_print -m "Слияние изменений из feature/111_add_print в develop"
git push
19. Ашалеть, что это за ЗВЕРЬ?
git rebase
Команда используется для интеграции изменений из одной ветки в другую. Она позволяет перенести или "переписать" серию коммитов из одной ветки в другую, сохраняя линейную историю. Это полезно для упрощения истории проекта и устранения ненужных коммитов слияния.
В Visual Studio Code (VS Code) можно наглядно увидеть графическую визуализацию истории коммитов на ветке develop:
Или при помощи этих команд:
git log --oneline
или
git log --oneline --graph --decorate --all
Возьмем последние два коммита:
git rebase -i HEAD~2
Выйдет такая страница:
pick abac516 Add print function
pick 5201b7f Убрал pass в console.log()
pick 8699ff2 Make print
# Rebase 1e6c9c2..aeba1fd onto 1e6c9c2 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
...
Основные команды:
-
p, pick <commit>— оставить коммит как есть -
r, reword <commit>— оставить изменения, но изменить сообщение коммита -
e, edit <commit>— остановиться на этом коммите для правок (можно добавить/изменить файлы) -
s, squash <commit>— объединить с предыдущим коммитом (сохраняя сообщение текущего) -
f, fixup [-C | -c] <commit>— объединить с предыдущим, но игнорировать его сообщение -
d, drop <commit>— удалить коммит (опасно — приведёт к потере изменений)
Если ты хочешь изменить историю, но не удалить изменения, то никогда не используй drop или fixup без понимания последствий.
Как мы можем увидеть у нас не попали merge (слияния веток). Merge commit-ы — это специальные коммиты, которые Git обрабатывает особо при rebase.
Попробуем переименовать один из коммитов. О том как пользоваться vim найдете в Работа с текстовым редактором vim:
pick abac516 Add print function
r 5201b7f Убрал pass в console.log()
pick 8699ff2 Make print
...
У нас появится опять конфликт, решаем, пишем git rebase --continue, и далее меняем сообщение в редакторе у commit на:
Убрал pass в console.log(). UPD: git rebase
Делаем отправку:
git push --force-with-lease
--force-with-lease безопаснее, чем --force: он проверит, не поменялась ли удалённая ветка за время твоей работы.
Как мы видим многие коммиты потерлись. Это происходит потому, что цель rebase — сделать историю линейной, а не сохранять информацию о слияниях.
git rebase лучше всего использовать, когда ты работаешь один над своей веткой, не публичной и тебе нужно изменить коммит, его сообщение, объединить несколько в один. Но как показывает практика, чтобы применять эту команду — нужно больше работы с ней.
Конечно, можно вернуться к предыдущему состоянию, но оно уже будет немного видоизменено:
git reset --hard origin/develop
git merge feature/111_add_print
git push
20. Просмотр различий между файлами
git diff
Команда используется для отображения различий между состояниями файлов в вашем репозитории Git. Она позволяет сравнивать изменения, которые произошли в файлах между различными состояниями, такими как рабочий каталог, индекс (staging area) и коммиты.
Давайте добавим различия, что увидеть работу данной команды. Добавим в файл index.html строку:
echo "<span>What is diff!</span>" >> index.html
И в файл index.css:
echo "span { color: red; }" >> index.css
При выполнении команды git diff получим:
diff --git a/index.css b/index.css
index 6dd919a..9e7b7bf 100644
Binary files a/index.css and b/index.css differ
diff --git a/index.html b/index.html
index db400e4..8ea75d9 100644
Binary files a/index.html and b/index.html differ
Если у Вас что-то подобное значит у Вас файл сохранен в неверном формате.
Если напишем команду git diff --text, то увидим строки, которые нельзя прочитать. Все дело в кодировке и русские символы будут видны как кракозябры. Исправить это можно, сохранив файл с определенной кодировкой.
В VS CODE меняется так: нажмите
Ctrl+Shift+P, введитеChange File Encoding, затем выберитеSave with Encodingи наконец-тоUTF-8.
После изменения вызов git diff покажет читаемую информацию:
diff --git a/index.css b/index.css
index b36d0b9..99d90d6 100644
--- a/index.css
+++ b/index.css
@@ -1,2 +1,3 @@
* { margin: 0; }
p { text-align: center; }
+span { color: red; }
diff --git a/index.html b/index.html
index 410a29a..acd0531 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
<p>Hello Git!</p>
+<span>What is diff!</span>
Если измененные файлы добавлены в индекс, то точно такую же информацию можно увидеть при выполнении команды:
git status -v
При сравнении с веткой master вдобавок получим index.js:
git diff master
...
+<p>I made my first push!</p>
\ No newline at end of file
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..43d2c75
--- /dev/null
+++ b/index.js
@@ -0,0 +1 @@
+console.log(pass)
Основные команды:
-
git diff index.html— вывести изменения только для определенного файла. -
git diff --staged— просмотр изменений, добавленных в индекс -
git diff <commit1> <commit2>— сравнение изменений между двумя коммитами по их хэшам -
git diff <branch1> <branch2>— сравнение изменений между ветками -
git diff --name-only— вывести только имена файлов, в которых произошли изменения. -
git diff -- *.css— сравнивает все файлы с расширением.css.
Менее юзаемые команды
Далее будут описаны команды, менее употребляемые при написании кода, но тоже важные.
21. Просмотр различий и редактирование файлов
git difftool
Команда позволяет использовать внешние дифф-утилиты для просмотра различий между файлами, а также менять код внутри файла.
Команда git difftool является дополнением команды git diff, но главное отличие — она умеет также и редактировать файлы.
Теперь используем команду.
This message is displayed because 'diff.tool' is not configured.
See 'git difftool --tool-help' or 'git help config' for more details.
'git difftool' will now attempt to use one of the following tools:
kompare emerge vimdiff nvimdiff
Viewing (1/2): 'index.css'
Launch 'vimdiff' [Y/n]?
Вводим Y и Enter, попадаем в редактор vim для редактирования файла.
Как работать в данном редакторе описано ранее в Работа с текстовым редактором vim:
При помощи данной команды мы также можем сравнивать ветки, коммиты и отдельные файлы.
Основные команды:
git difftool --tool-help: Показывает список доступных инструментов. Так как я работаю в VS Code, то в списке доступных покажется vscode. Вы можете установить его как дефолтный инструмент командой:
git config --global diff.tool vscode
И тогда будет открываться не в консоли, а во вкладке VS Code. Закрытие вкладки — выход из difftool.
22. Работа с удалёнными репозиториями
git remote
Команда git remote используется для управления удалёнными репозиториями в Git.
Основные команды:
-
git remote -v— выводит список имён удалённых репозиториев c URL-ом. -
git remote add <name> <url>— добавление удалённого репозитория -
git remote remove <name>— удаление удалённого репозитория -
git remote rename <old-name> <new-name>— переименование удалённого репозитория -
git remote set-url <name> <new-url>— изменение URL удалённого репозитория
23. Теги
git tag
Команда git tag используется для создания, просмотра и управления тегами в Git. Теги — это метки, которые обычно используются для обозначения стабильных версий проекта (например, v1.0.0, v2.1.3 и т.д.).
Выведем все коммиты:
Добавим для коммита fb07e9c Убрал pass в console.log(). UPD: git rebase тег:
git tag -a v1.0.0 fb07e9c -m "Рабочая версия v1.0.0"
Команда git tag -n выводит информацию:
v1.0.0 Рабочая версия v1.0.0
Команда git show v1.0.0 выводит информацию:
tag v1.0.0
Tagger: Ivan <ivan@gmail.com>
Date: Fri Jun 13 20:20:22 2025 +0300
Рабочая версия v1.0.0
commit fb07e9cdd9c778bb52bb4b3b08f9fc37f512dba4 (tag: v1.0.0)
Author: Ivan <ivan@gmail.com>
Date: Thu Jun 12 23:37:23 2025 +0300
Убрал pass в console.log(). UPD: git rebase
diff --git a/index.js b/index.js
index 2db8952..913f3b6 100644
Binary files a/index.js and b/index.js differ
Отправим в репозиторий тег:
git push origin v1.0.0
Теперь перейдя в удаленный репозиторий, мы увидим наш тег:
Основные команды:
-
git tag— выводит список всех тегов -
git tag -a <tagname> -m "message"— создаёт аннотированный тег с сообщением -
git tag <tagname> <commit>— создаёт тег на определённом коммите -
git show <tagname>— показывает информацию о теге: автор, дата, сообщение, изменения -
git tag -n— показывает список тегов с кратким сообщением (если есть) -
git push origin <tagname>— отправляет указанный тег на удалённый репозиторий -
git tag -d <tagname>— удаляет тег из локального репозитория -
git push origin --delete <tagname>— удаляет тег из удалённого репозитория
24. Восстановления файлов из индекса или коммитов
git restore
Команда git restore предназначена для восстановления файлов из индекса или коммитов, заменяя собой некоторые функции git checkout и git reset. Она делает работу с откатом изменений более понятной и явной.
Основные команды:
-
git restore <file>— отменяет локальные изменения. Никак не влияет, если файл в индексе -
git restore --staged <file>— убирает файл из индекса (не трогает рабочую директорию) -
git restore --staged .— убирает все файлы из индекса (не трогает рабочую директорию) -
git restore -- .— похоже на командуgit checkout -- .. Восстанавливает все файлы в текущем каталоге и подкаталогах
25. Применение коммитов из одной ветки на другую
git cherry-pick
Команда git cherry-pick позволяет применить один или несколько конкретных коммитов из одной ветки на другую. Это удобно, если ты хочешь перенести только определённые изменения, а не всю ветку целиком.
Переключимся на ветку master для наглядной демонстрации, получим коммиты develop и выполним:
git log develop --oneline --reverse
60c5923 (HEAD -> master, origin/master, origin/HEAD) Initial commit
efd81d6 First commit on develop
abac516 Add print function
5201b7f (origin/hotfix/change_clg, hotfix/change_clg) Убрал pass в console.log()
f709a7b Слияние изменений из hotfix/change_clg в develop
040f399 Merge branch 'develop' into feature/111_add_print
8699ff2 (origin/feature/111_add_print, feature/111_add_print) Make print
fb07e9c (tag: v1.0.0) Убрал pass в console.log(). UPD: git rebase
a4433a3 Make print
e5d24be (origin/develop, develop) Merge branch 'feature/111_add_print' into develop
Возьмем допустим коммит 8699ff2:
git cherry-pick --edit 8699ff2
Откроется редактор, пропишем Cherry-pick from feature/111_add_print и запушим git push. Как видим, наша ветка стянула состояние ветки feature/111_add_print, имеющееся на данном коммите.
Если необходимо откатить коммит и убрать его из истории, то просто делаем следующие шаги:
git log --oneline
3dd9bb9 (HEAD -> master, origin/master, origin/HEAD) Cherry-pick from develop
60c5923 Initial commit
git reset --hard 60c5923
HEAD is now at 60c5923 Initial commit
git push -f
Основные команды:
-
git cherry-pick <commit>— применяет указанный коммит на текущей ветке -
git cherry-pick <commit1>..<commit2>— применяет все коммиты междуcommit1иcommit2(включаяcommit2, исключаяcommit1) -
git cherry-pick <commit1>^..<commit2>— применяет все коммиты отcommit1доcommit2включительно -
git cherry-pick --edit (-e)— позволяет редактировать сообщение коммита перед применением -
git cherry-pick --no-commit (--n)— применяет изменения в индекс, но не создаёт коммит -
git cherry-pick --continue— продолжает процесс после разрешения конфликтов -
git cherry-pick --abort— отменяет cherry-pick и возвращает всё к исходному состоянию -
git cherry-pick --quit— выходит из процесса cherry-pick без изменений
26. Откат изменений
git revert
Команда git revert используется для отката изменений, создавая новый коммит, который "отменяет" изменения, внесённые ранее указанным коммитом. Это безопасный способ отката, потому что он не переписывает историю (в отличие от git reset).
Добавим какие-нибудь данные echo "<span>git revert</p>" > index.html и запушим. Мы можем откатить последний коммит через HEAD или через его хэш:
git log --oneline
f5ecd54 (HEAD -> master, origin/master, origin/HEAD) Git revert test
60c5923 Initial commit
git revert HEAD
или
git revert f5ecd54
В редакторе можем поменять сообщение коммита у revert и можем пушить. Сам же файл index.html откатился к предыдущей версии.
Основные команды:
-
git revert <commit>— откатывает указанный коммит, создавая новый коммит с обратными изменениями -
git revert --edit (-e)— позволяет редактировать сообщение коммита перед сохранением -
git revert --no-edit— применяет revert без изменения сообщения -
git revert --no-commit (-n)— применяет изменения в рабочую область, но не создаёт коммит -
git revert --continue— продолжает процесс после разрешения конфликтов -
git revert --abort— прерывает процесс revert и возвращает всё к исходному состоянию -
git revert --quit— выходит из режима revert без изменений -
git revert --mainline <n>— используется при откате merge-коммита; указывает, какую родительскую ветку считать основной (например, 1 или 2)
Основные команды
-
Клонирование репозитория —
git clone https://github.com/<Ваш аккаунт>/<Ваш репозиторий>.git . -
Cписок имён удалённых репозиториев c URL-ом —
git remote -v -
Добавление файлов в индекс —
git add . -
Удаление файлов из индекса —
git reset -
Создание коммита —
git commit -m "Сообщение коммита" -
Добавить забытые файлы в предыдущий коммит без изменения сообщения:
git add . git commit --amend --no-edit -
Отправить изменения в удаленный репозиторий —
git push -
Создание ветки и переключение на нее —
git switch -c <новая_ветка> -
Просмотр локальных и удалённых веток —
git branch -a -
Принудительное удаление ветки —
git branch -D <ветка> -
Переименовать ветку —
git branch --move (-m) <старая_ветка> <новая_ветка> -
Состояние рабочего каталога и индекса —
git status -
Просмотр истории коммитов в удобном виде —
git log --graph --oneline -
Восстановление всех файлов, не вошедших в индекс, до состояния последнего коммита —
git checkout -- . -
Убирает все файлы из индекса —
git restore --staged ...- все файлы, можно заменить на название определенного файла. -
Слияние изменений веток —
git merge --no-ff <ветка, которую хотим слить в текущую> -m "<Сообщение>" -
Извлечение и слияние изменений —
git pull -
Удаление файла из индекса (staging area) и из remote репозитория при следующем push, но сохранение в рабочей директории —
git rm --cached <имя-файла>.-rфлаг действует для папок. -
Если необходимо откатить коммит и убрать его из истории, то просто делаем следующие шаги:
git log --oneline 3dd9bb9 (HEAD -> master, origin/master, origin/HEAD) Cherry-pick from develop 60c5923 Initial commit git reset --hard 60c5923 HEAD is now at 60c5923 Initial commit git push -f
Вывод
Вот и всё! Мы разобрали основные команды Git, которые помогут тебе эффективно управлять проектами и работать с кодом. Надеюсь, эта статья помогла тебе разобраться в базовых принципах работы с Git.