Полезные команды Git, которые стоит взять на вооружение
Все мы – инженеры-программисты – ежедневно используем Git,однако большинство специалистов оперируют исключительно базовыми командами, такими как add, commit, push и pull – как-будто мы до сих пор живем в 2005 году.
C тех пор в Git появилось множество функций, использование которых может значительно облегчить Вашу жизнь, поэтому давайте рассмотрим некоторые из сравнительно недавно добавленных современных команд git, о которых Вы обязательно должны знать.
Switch
Новая команда, появившаяся в 2019 году, в рамках версии 2.23, - git switch, которую можно использовать для переключения веток:
gitswitch other-branchgitswitch -# Switch back to previous branch, similar to "cd -" gitswitch remote-branch# Directly switch to remote branch and start tracking it
Здорово, но мы уже давно переключаем ветки в Git с помощью git checkout, так зачем нужна отдельная команда? git checkout - универсальная команда, которая может проверять и восстанавливать конкретные файлы или даже конкретные коммиты, а новая git switch предназначена исключительно для переключения веток. Кроме того, эта команда выполняет дополнительные проверки на корректность, которых нет у checkout, например, switch прервет операцию, если она может привести к потере локальных изменений.
Restore
Еще одна новая подкоманда/функция, добавленная в Git версии 2.23, - git restore, с помощью которой мы можем восстановить файл до последней зафиксированной версии:
# Unstage changes made to a file, same as "git reset some-file.py" gitrestore --staged some-file.py# Unstage and discard changes made to a file, same as "git checkout some-file.py" gitrestore --staged --worktree some-file.py# Revert a file to some previous commit, same as "git reset commit -- some-file.py" gitrestore --source HEAD~2 some-file.py
Комментарии в приведенном выше фрагменте объясняют работу различных git restore. В целом, git restore заменяет и упрощает некоторые случаи использования git reset и git checkout, которые уже и без того являлись перегруженными функциями.
Sparse Checkout
Следующая интересная и при этом немного запутанная команда - sparse-checkout, которая была добавлена в Git 2.25, вышедшую 13 января 2020 года.
Допустим, у Вас - большой монорепозиторий с микросервисами, разделенными по отдельным каталогам, и такие команды, как checkout или status, будут работать слишком медленно именно из-за размера репозитория. При этом, возможно, из всего этого многообразия Вам нужно только один каталог. Как раз в этом случае на помощь и приходит git sparse-checkout:
$gitclone --no-checkout https://github.com/derrickstolee/sparse-checkout-example$cdsparse-checkout-example$gitsparse-checkout init --cone# Configure git to only match files in root directory$gitcheckout main# Checkout only files in root directory$lsbootstrap.sh LICENSE.md README.md$gitsparse-checkoutsetservice/common$lsbootstrap.sh LICENSE.md README.mdservice$ tree.
.├── bootstrap.sh├── LICENSE.md├── README.md└──service├── common│ ├── app.js│ ├── Dockerfile......
В приведенном выше примере мы сначала клонируем репозиторий, не проверяя файлы. Затем для настройки git на проверку файлов только в его корне мы используем git sparse-checkout init --cone. Таким образом, после выполнения checkout у нас будет только 3 файла, а не целое дерево. Для загрузки/проверки определенного каталога мы используем git sparse-checkout set .....
Как уже говорилось ранее, это может быть очень удобно при локальной работе с огромными репозиториями, но это также полезно и для повышения производительности конвейера, когда Вы хотите собрать/развернуть только какую-то часть монорепозитория и Вам не нужно проверять все подряд.
Worktree
Нередко бывает так, что приходится выполнять сразу несколько операций в рамках одного приложения (репозитория). Или практически каждый хотя бы раз сталкивался с ситуацией, когда в середине работы над каким-то запросом возникает критическая ошибка.
В таком случае Вам нужно либо клонировать несколько версий/ветвей репозитория, либо хранить/выбрасывать то, над чем Вы работали все это время. Выходом из таких ситуаций как раз и является git worktree, выпущенная 24 сентября 2018 года:
gitbranch# * dev # master gitworktree list# /.../some-repo ews5ger [dev] gitworktreeadd-b hotfix ./hotfix master# Preparing worktree (new branch 'hotfix') # HEAD is now at 5ea9faa Signed commit. gitworktree list# /.../test-repo ews5ger [dev] # /.../test-repo/hotfix 5ea9faa [hotfix] cdhotfix/# Clean worktree, where you can make your changes and push them
Эта команда позволяет проверять сразу несколько веток одного репозитория. В примере выше у нас есть 2 ветки dev и master. Допустим, мы работаем над функцией в ветке dev, но нам сказали срочно исправить возникшую ошибку. Вместо того чтобы сохранить изменения и сбросить ветку, мы создадим новое рабочее дерево в подкаталоге ./hotfix из ветки master. Затем перейдем в этот каталог, внесем изменения, выложим их и вернемся в исходное рабочее дерево.
Bisect
И, наконец, git bisect, не такая новая, как предыдущие команды (Git 1.7.14, выпущен 13 мая 2012 года), но все же поговорим и о ней.
Как описано в официальном источнике, «git-bisect выполняет бинарный поиск по истории коммитов для того, чтобы как можно быстрее определить коммит, в котором была допущена ошибка»:
gitbisect startgitbisect bad HEAD# Provide the broken commit gitbisect good 479420e# Provide a commit, that you know works # Bisecting: 2 revisions left to test after this (roughly 1 step) # [3258487215718444a6148439fa8476e8e7bd49c8] Refactoring. # Test the current commit... gitbisect bad# If the commit doesn't work gitbisect good# If the commit works # Git bisects left or right half of range based on the last command # Continue testing until you find the culprit gitbisect reset# Reset to original commit
Мы начинаем с явного запуска сеанса бисекции с помощью git bisect start, после чего предоставляем неработающий коммит (скорее всего, HEAD), а также последний известный нам работающий коммит. Получив эту информацию, git проверит коммит, находящийся на полпути между «плохим» и «хорошим» коммитом. В этот момент нам также нужно проверить, есть ли в этой версии ошибка или нет - для этого мы используем git bisect good для того, чтобы сообщить git, что все в порядке, или git bisect bad в том случае, если текущий коммит у нас «плохой» . Повторяем этот процесс до тех пор, пока не останется ни одного коммита, и git сообщит нам, в каком именно коммите возникла проблема.
Заключение
Если Вы ищете решение какой-либо проблемы, связанной с git, то, скорее всего, обратитесь к StackOverflow и обязательно найдете ответы, набравшие несколько тысяч голосов. Вполне возможно, что они еще до сих пор актуальны, но, скорее всего, были написаны около десяти лет. Сами понимаете, что за это время могло появиться что-то более легкое и эффективное. Поэтому, когда Вы сталкиваетесь с какой-либо проблемой git, лучше обращайтесь к git docs, содержащим новые функции, или прочитайте man pages, где можно найти множество флагов и опций, которые были добавлены к старым добрым командам.