Командный интерпретатор bash позволяет задавать произвольные алиасы для разных команд и выражений. Алиасы не являются командами сами по себе, но им, как и командам, можно передавать аргументы. Алиасы позволяют сделать вызов громоздких команд очень простым, с легко запоминающимися названиями.
Использовать Git я привык исключительно из консоли, но на ввод длинных команд с разными аргументами тратится значительное количество времени. Поэтому я ввёл практику использования алиасов. Для безопасных команд я использовал короткие алиасы, которые по сути стали горячими клавишами, а для функциональных — простые короткие слова из состава команд Git. Если команда опасная, то можно сделать её в два слова, написанных через дефис, для исключения случайного ввода. На самом деле, использование алиасов для работы с Git широко практикуется, я решил лишь преподнести отдельный вариант подборки алиасов, которые для меня оказались очень удобными.
Формат задания алиаса имеет следующий вид:
alias name="<выполняемый код>"
Основной проблемой алиасов является то, что они не подхватываются автоматически механизмом автодополнения кода. Их написание отличается от тех команд, которые зарегистрированы в системе автодополнения, поэтому приходится дополнительно регистрировать алиасы, назначая им соответствующие спецификации автодополнения (compspec) через встроенную в bash команду complete
. В случае с Git над complete
существует обёртка __git_complete
, в которую необходимо передавать предопределённые функции-обёртки, начинающиеся с префикса _git_
и оканчивающиеся названием подкоманды git. В Ubuntu весь связанный с этим код можно посмотреть в файле /usr/share/bash-completion/completions/git
.
Алиас |
Действие |
|
Получить изменения с сервера |
|
Просмотреть текущее состояние локального репозитория |
|
Просмотреть текущее состояние локального репозитория и количество изменённых строк |
|
Просмотреть изменения, сделанные в файлах и ожидающие подтверждения, в стандартном diff-формате |
|
Просмотреть изменения, сделанные в файлах и ожидающие подтверждения, с выделением одним только цветом |
|
Список последних коммитов в кратком формате. |
|
Список последних коммитов с развёрнутой информацией о них. |
|
Переход на другую ветку или коммит, создание новой ветки с опцией |
|
Получить изменения с сервера и влить их в текущую ветку. |
|
Сделать коммит (зафиксировать изменения). |
|
Добавить файлы или изменения в будущий коммит. |
|
Отменить добавление изменений в будущий коммит. |
|
Отправить новые коммиты на сервер. |
|
Отправить коммиты на сервер с перезаписью их истории, если другие люди не успели отправить туда свои коммиты. |
|
Влить заданную ветку в текущую. |
|
Добавить изменения в уже сделанный коммит или изменить его комментарий. |
|
Выполнить перезапись истории коммитов, например, переместив коммиты в конец другой ветки. |
|
Переименовывание или удаление локальной ветки |
|
Применить в текущей ветке отдельные существующие коммиты. |
|
Сохранить свои текущие изменения во временное хранилище. |
|
Применить свои текущие изменения из временного хранилища, но не удалять и оттуда. |
|
Забрать свои изменения из временного хранилища и применить их. |
Ниже приведено примерное содержимое файла ~/.bash_aliases
с основными алиасами Git и кодом их автоматической регистрации в механизме автодополнения командой строки.
#!/bin/bash
alias f="git fetch --tags"
alias s="git status"
alias ss="git status && git diff --shortstat"
alias d="git diff"
alias dd="git diff --word-diff=color"
alias l="git log -n 20 --graph --pretty=format:'%Cred%h%Creset %an: %s / %Cgreen%cr%Creset %Creset %C(yellow)%d%Creset' --abbrev-commit --date=relative"
alias ll="git log"
alias go="git checkout"
#или alias gg="git checkout"
alias pull="git pull"
alias commit="git commit"
alias add="git add"
alias reset="git reset"
alias push="git push"
alias push-fix="git push --force-with-lease"
alias merge="git merge"
alias amend="git commit --amend"
alias rebase="git rebase"
alias branch="git branch"
alias pick="git cherry-pick"
alias stash="git stash"
alias apply="git stash apply"
alias pop="git stash pop"
# Регистрируем алиасы в системе автодополнения
git_completions="/usr/share/bash-completion/completions/git"
if [ -f "${git_completions}" ]; then
source "${git_completions}"
# Получаем массивы алиасов и соответствующих им команд git
cmds=( $(alias | grep -v ss | grep -Po '(?<=git )[\w-]+' | sed -r 's/[ -]+/_/g') )
aliases=( $(alias | grep -v ss | grep git | grep -Po '(?<=alias )\w+') )
# Регистрируем каждый алиас
for (( i = 0; i < ${#aliases[@]}; i++ )); do
a="${aliases[$i]}"
cmd="${cmds[$i]}"
__git_complete "${a}" _git_"${cmd}"
done
fi
Для того, чтобы файл с алиасами применялся при входе в систему, необходимо добавить его подключение в файл ~/.bashrc
с помощью команды source
(или .
). Файл ~/.bashrc
запускается на исполнение всегда при старте командного интерпретатора bash, поэтому если файл редактировался из консоли, потребуется её заново открыть или запустить вложенный командный интерпретатор bash.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
Алиасы s
, d
и l
простые, дают необходимый минимум информации. Задумка двухбуквенных в том, чтобы дать слегка больше информации, если это требуется. С помощью f
можно получить последние изменения в репозитории и влить их в текущую ветку с помощью pull
или pull -r
. Через l
можно посмотреть, что за новые коммиты прилетели в ветку, или что было последним из изменений, а через ll
— подробно изучить коммиты. Переключиться на другую ветку можно через go
, создать новую ветку можно через go -b
. При создании коммита, в общем случае, сначала вводится s
, проверяется на какой мы ветке, какие файлы требуется добавить, затем d
, чтобы проверить свои изменения. Через add
добавляются файлы (или add -i
для выбора отдельных изменений в файлах), через commit -m
создаётся новый коммит. Если вдруг в тексте сообщения коммита оказалась опечатка, можно быстро всё поправить через amend
. Если в main-ветку успели прилететь новые коммиты, можно сделать rebase main
. И потом сделать push
. Если ветка своя собственная, то можно делать rebase -i
с исправлениям прошлых коммитов и отправить модифицированные коммиты через push-fix
.
Если шла работа, но срочно понадобилось переключиться на другую ветку, можно временно убрать свои изменения через stash
, переключиться на другую ветку через go
. Потом можно вернуть изменения с помощью apply
или pop
. Отдельные коммиты из других веток можно применять с помощью pick
, также это может быть полезным, если случайно сделать изменения в отделённом HEAD (например, в подмодуле).
Алиасы могут совпадать с существующими командами. Если такие команды обычно не используются, то это проблемой не является. Если же команды понадобятся, то в случае исполняемых файлов всегда можно указать полный путь к файлу. Не будет проблем и с командами, которые запускаются от имени суперпользователя, поскольку алиасы прописаны лишь для непривилегированного пользователя. Если используется язык Go, то с использованием алиаса go
могут возникнуть проблемы. В качестве решения можно изменить алиас на gg
или gc
, либо же сделать алиас golang
для команды go
. Здесь кому как удобнее.
В Ubuntu 21.10 при использовании алиаса над git checkout
выводятся сообщения об ошибках. Происходит это из-за того, что одна из переменных в целочисленных сравнениях оказывается пустой. Вариантом подавления вывода ошибок является замена в файле /usr/share/bash-completion/completions/git
сравнения через квадратные скобки на арифметическое сравнение через двойные скобки, например, (( var1 < var2 ))
, в которых можно использовать названия переменных без предшествующего знака $
. Такое исправление работает и в zsh, на который автодополнение тоже рассчитано.
Патч, решающий проблему
--- /usr/share/bash-completion/completions/git 2021-08-09 15:29:27.000000000 +0300
+++ ./git 2022-04-08 23:32:38.501198226 +0300
@@ -1011,7 +1011,7 @@
if [ "$cmd" = "remote" ]; then
((c++))
fi
- while [ $c -lt $cword ]; do
+ while (( c < cword )); do
i="${words[c]}"
case "$i" in
--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
@@ -1187,7 +1187,7 @@
done
local wordlist="$1"
- while [ $c -lt $cword ]; do
+ while (( c < cword )); do
for word in $wordlist; do
if [ "$word" = "${words[c]}" ]; then
if [ -n "${show_idx-}" ]; then
@@ -1221,7 +1221,7 @@
done
local wordlist="$1"
- while [ $c -gt "$__git_cmd_idx" ]; do
+ while (( c > __git_cmd_idx )); do
((c--))
for word in $wordlist; do
if [ "$word" = "${words[c]}" ]; then
@@ -1283,7 +1283,7 @@
__git_has_doubledash ()
{
local c=1
- while [ $c -lt $cword ]; do
+ while (( c < cword )); do
if [ "--" = "${words[c]}" ]; then
return 0
fi
@@ -1449,7 +1449,7 @@
{
local i c="$__git_cmd_idx" only_local_ref="n" has_r="n"
- while [ $c -lt $cword ]; do
+ while (( c < cword )); do
i="${words[c]}"
case "$i" in
-d|-D|--delete|-m|-M|--move|-c|-C|--copy)
@@ -2479,7 +2479,7 @@
__git_config_get_set_variables ()
{
local prevword word config_file= c=$cword
- while [ $c -gt "$__git_cmd_idx" ]; do
+ while (( c > __git_cmd_idx )); do
word="${words[c]}"
case "$word" in
--system|--global|--local|--file=*)
@@ -3213,7 +3213,7 @@
_git_tag ()
{
local i c="$__git_cmd_idx" f=0
- while [ $c -lt $cword ]; do
+ while (( c < cword )); do
i="${words[c]}"
case "$i" in
-d|--delete|-v|--verify)
@@ -3388,7 +3388,7 @@
local __git_C_args C_args_count=0
local __git_cmd_idx
- while [ $c -lt $cword ]; do
+ while (( c < cword )); do
i="${words[c]}"
case "$i" in
--git-dir=*)
На практике я использую несколько меньший набор алиасов, в списке же привёл все, какие могут пригодиться в повседневной работе. Надеюсь, этот список кому-то окажется полезным, удачного использования!
Комментарии (34)
PlatinumThinker
13.04.2022 10:33+1
brownfox
13.04.2022 13:54Большая часть алиасов выполнена по схеме alias n='git n'
Идея настолько очевидная, что ценность статьи не очень понятна :)
andrey0700 Автор
13.04.2022 19:33Поделиться существующей практикой и идеями. Я уже достаточно давно использую алиасы, они оказались намного удобнее, чем вводить команды целиком, причём именно в таком виде, легко запоминаются, нет никакой путаницы, действия доводятся до автоматизма. Собственно, основной моей деятельностью в консоли является работа с git.
Ну и в интернете список алиасов всегда под рукой. :)
randomsimplenumber
13.04.2022 13:54dd и reset - существующие утилиты, к git никак не относятся.
andrey0700 Автор
13.04.2022 19:15-3dd используется или через sudo, или от имени суперпользователя. В обоих случаях алиасы работать перестают, поскольку прописаны у непривилегированного пользователя. На моей практике у меня не возникало проблем с существующими командами.
Если алиасы совпадают с командами, которые в норме не используются, то проблем нет. Именно поэтому я лишь про команду go упомянул.
Отразил данную информацию в статье.
randomsimplenumber
13.04.2022 23:44+2dd используется или через sudo, или от имени суперпользователя
dd используется по разному. Git, кстати, тоже. А делать алиасы, совпадающие с существующими программами, это вредительство.
andrey0700 Автор
14.04.2022 07:40Чем же это может вредить? С таким же успехом навредить может кастомизация горячих клавиш. Мне не нравится F2 для переименовывания файлов, я её на другое действие переназначаю. Алиасы предназначены для катомизации терминала под себя, как будет удобно именно отдельному человеку. Из людей, с кем я работал, один взял мой вариант, а другой сделал себе свои, совсем другие, алиасы.
Что касается пересечений с названиями команд, то писать /bin/dd будет даже более хорошей практикой в скриптах, поскольку исключает пересечение с алиасами. Если часто требуется выполнять эту команду из консоли, то можно не прописывать автоматическое подключение алиасов в bashrc, а инициализировать их раз в день в рабочей консоли отдельной командой. Либо же подобрать другое название, например, dc (diff, color).
И если уж называете вредительсвом, то давайте расшифровку того, что имеете в виду, какие именно случаи, и какой вред в этих случаях алиасы могут нанести.
wibotwi
14.04.2022 08:55В скриптах алиасы не работают. Вы можете в скриптах продолжать писать dd.
andrey0700 Автор
14.04.2022 19:42Большое спасибо за пояснение! Действительно. Этого момента не знал.
E_STRICT
14.04.2022 10:51писать /bin/dd будет даже более хорошей практикой в скриптах, поскольку исключает пересечение с алиасами
Такой скрипт не будет портабельным, потому абсолютный путь может отличаться на разных системах. Чтобы игнорировать алиас или шел функцию достаточно поместить название команды в кавычки либо запускать через
command
.
randomsimplenumber
14.04.2022 14:34Чем же это может вредить?
Ну, можно представить кулхацкера, который на своей любимой системе виндовз сделал глубокий апгрейд: поменял картинки и подписи на всех ярлыках, потому что ему удобно, когда вместо иконки 'мой компьютер' - мусорная корзина. Вредит он только себе - с такими нестандартными привычками за любым другим компьютером ему будет неудобно.
bullkasizumom
13.04.2022 18:48+2почему бы не использовать .gitconfig для алиасов и не плодить конфликты в bash командах? или это очередная статья из разряда придумал не знаю для чего, но могу вот так...
souls_arch
14.04.2022 07:18+3И сколько секунд экономит нам pull вместо git pull? Сейчас угадаю - 0. При скорости печати 200-300зн/м вслепую и редкости операции.
Там и так все сокращено, куда еще? Вы еще команды линуха/макОС уже до букв аббревиатур сокращенные посокращайте
В громоздких запросах бд - псевдонимы необходимость. А в гите то на кой?
Это мое мнение, можно пинать.
saipr
14.04.2022 08:26+1Если не предвзято взглянуть на первую часть статьи, то, в принципе, имеем неплохую подсказку по командам git для начинающего пользователя.
wibotwi
14.04.2022 08:58А зачем вам алиас на git pull? Я ума не приложу зачем эта команда может понадобиться. Я в 100% случаев зову git pull --rebase.
Zuy
14.04.2022 10:07А что не так с git pull? Ну вот лежит у меня master, хочу я с сервера свежие комитты подтянуть в него, так и использую git pull. Или я чего-то не понимаю?
mayorovp
14.04.2022 11:24+1Проблема в том, что эти свежие комитты будут вмержены в вашу текущую ветку, причём ваша ветка будет считаться основной. Это не проблема если вы работаете в отдельной ветке, которую потом будете мержить обратно, но если результат git pull запушить — большинство инструментов построения списков изменений поломаются.
Ну а если вы и вовсе PR готовите, то там комиты слияния выглядят попросту некрасиво.
arelive
14.04.2022 11:27А теперь ищем в поиске гитхаба 'dotfiles', открываем любой репозиторий, заходим в .bashrc / .zshrc и видим, что вешать алиасы на все частые команды, не только git - повсеместная практика. Заодно понимаем, что алиасы 'll', 'gs' и тем более 'go' - очень и очень плохие.
rionnagel
15.04.2022 15:47tudoy/sudoy/getoverhere/nunafig
Вообще я иногда испльзую аллиасы только при хронических ошибках и сильном постоянстве (ls/sl, чтоб паровозик не вызывал, ip ч тоб всегда был с -c и т.д.).
Как бы не звучало, но имхо по аллиасам мана достаточно.
sergio_nsk
Не надо так делать.
dd
- это программа,go
- это компилятор,ll
- частоls -l
,reset
- это команда шелла. Неужели сложно написатьgit
в начале?Примерно так
Bash documentation:
E_STRICT
Зачем вообще использовать Баш вместо Гит алиасов?
13werwolf13
возможно потому что bashrc/zshrc/etc с собой таскать проще чем bashrc+gitconf+ещёпачкувсего
E_STRICT
Про какую пачку речь? Все алиасы хранятся в одном .gitconfig файле.
13werwolf13
но кроме гита используется ещё 100500 софтин и утилит на постоянной основе
storoj
можно сделать git init в домашней директории и синхронизировать все свои настройки на всех компьютерах
13werwolf13
увы но нет
прийдётся писать огромный .gitignore файлик в котором заигнорено будет больше чем попадёт в репу потому что есть некотоорые софтины к примеру гуглохром запуск двух экземпляров которых одновременно на разных тачках приведут к проблемам, а есть софтины дотфайлы которых нет смысла таскать с собой везде (те кто пишет на ноде, го или расте сейчас дружно закивали головой). к тому же git не автоматизирует синхронизацию а лишь уменьшает кол-во действий для неё
я использую resilio (да мне просто лень переехать на synthing) синхроню отдельную директорию из которой часть конфигов отправляю в хомяк симлинками а часть через mount bind, и это тоже костылизм потому что некоторые софтины не могут работать с конфигом через симлинк (примеры rclone и cherrytree). приходится постоянно руками (ну не совсем руками, через ansible но всё равно не автоматически) поддерживать все нужные связи между папкой синхрона и хомяком на разных тачках (у меня это два pc и два ноута).
давно есть идея создать для этого инструмент который бы заранее знал каким конфигам можно симлинк а каким маунтбинд и при появлении определённого конфига на одной тачке делал всё необходимое на второй. но пока это идея в зачаточной стадии
storoj
Есть настройка ignore untracked: пока явно не начнёшь трекать какой-нибудь конфиг, git status будет пуст.
13werwolf13
не знал о таком сыпасиба.
storoj
git config --local status.showUntrackedFiles no