Git псевдоним с позиционными параметрами
В основном я пытаюсь сделать псевдоним:
git files 9fa3
... выполнить команду:
git diff --name-status 9fa3^ 9fa3
но git, как представляется, не передает позиционные параметры команде alias. Я пробовал:
[alias]
files = "!git diff --name-status $1^ $1"
files = "!git diff --name-status {1}^ {1}"
... и несколько других, но это не сработало.
Вырожденным случаем было бы:
$ git echo_reverse_these_params a b c d e
e d c b a
... как я могу сделать эту работу?
Ответы
Ответ 1
Наиболее очевидным способом является использование функции оболочки:
[alias]
files = "!f() { git diff --name-status \"$1^\" \"$1\"; }; f"
Алиас без !
рассматривается как команда Git; например commit-all = commit -a
.
С помощью !
он запускается как собственная команда в оболочке, позволяя вам использовать более сильную магию следующим образом.
UPD
Поскольку команды выполняются в корневом каталоге репозитория, вы можете использовать переменную ${GIT_PREFIX}
при обращении к именам файлов в командах
Ответ 2
Вы также можете напрямую ссылаться на sh
(вместо создания функции):
[alias]
files = !sh -c 'git diff --name-status $1^ $1' -
(Обратите внимание на тире в конце строки - вам это нужно.)
Ответ 3
Псевдоним, который вы ищете, это:
files = "!git diff --name-status \"$1\"^ \"$1\" #"
С проверкой аргумента:
files = "!cd -- \"${GIT_PREFIX:-.}\" && [ x$# != x1 ] && echo commit-ish required >&2 || git diff --name-status \"$1\"^ \"$1\" #"
Финал #
важен - он предотвращает обработку всех аргументов, предоставленных пользователем оболочкой (он их комментирует).
Примечание: git
помещает все аргументы, предоставленные пользователем, в конце командной строки. Чтобы увидеть это в действии, попробуйте: GIT_TRACE=2 git files abcd
Выделенные (из-за вложенности) кавычки важны для имен файлов, содержащих пробелы, или "; rm -rf --no-preserve-root/;
)
Ответ 4
Используйте GIT_TRACE = 1, описанные на странице git man, чтобы сделать обработку псевдонима прозрачной:
$ git config alias.files
!git diff --name-status $1^ $1
$ GIT_TRACE=1 git files 1d49ec0
trace: exec: 'git-files' '1d49ec0'
trace: run_command: 'git-files' '1d49ec0'
trace: run_command: 'git diff --name-status $1^ $1' '1d49ec0'
trace: exec: '/bin/sh' '-c' 'git diff --name-status $1^ $1 "[email protected]"' 'git diff --name-status $1^ $1' '1d49ec0'
trace: built-in: git 'diff' '--name-status' '1d49ec0^' '1d49ec0' '1d49ec0'
trace: run_command: 'less -R'
trace: exec: '/bin/sh' '-c' 'less -R' 'less -R'
MM TODO
Ваши исходные команды работают с git версией 1.8.3.4 (Eimantas отметил, что это изменилось в 1.8.2.1).
Параметры sh -c '..' --
и f() {..}; f
как чисто обрабатывают параметры [email protected]по-разному (см. GIT_TRACE). Добавление "#" к псевдониму также позволит позиционные параметры, не оставляя конечных.
Ответ 5
Как указано Drealmer выше:
"Будь осторожен! будет работать в корне репозитория, поэтому использование относительных путей при вызове вашего псевдонима не даст ожидаемых результатов. - Drealmer Aug 8 '13 в 16:28"
GIT_PREFIX
устанавливается в git в подкаталог, в котором вы находитесь, вы можете обойти это, сначала изменив каталог:
git config --global alias.ls '! cd "$ {GIT_PREFIX: -.}"; ls -al'
Ответ 6
Я хотел сделать это с помощью псевдонима, который делает это:
git checkout $1;
git merge --ff-only $2;
git branch -d $2;
В конце концов, я создал оболочку script с именем git -m, которая имеет этот контент:
#!/bin/bash -x
set -e
#by naming this git-m and putting it in your PATH, git will be able to run it when you type "git m ..."
if [ "$#" -ne 2 ]
then
echo "Wrong number of arguments. Should be 2, was $#";
exit 1;
fi
git checkout $1;
git merge --ff-only $2;
git branch -d $2;
Это имеет то преимущество, что оно гораздо более разборчиво, потому что оно на нескольких линиях. Кроме того, мне нравится звонить bash с помощью -x
и set -e
. Возможно, вы можете сделать все это как псевдоним, но это было бы очень уродливо и трудно поддерживать.
Поскольку файл имеет имя git-m
, вы можете запустить его следующим образом: git m foo bar
Ответ 7
Просто наткнулся на нечто подобное; Надеюсь, он будет опубликовать мои заметки. Одна вещь, которая смущает меня в отношении псевдонимов git
с аргументами, вероятно, происходит из git help config
(у меня есть git версия 1.7.9.5):
Если расширение псевдонима имеет префикс с восклицательным знаком, оно будет рассматриваться как команда оболочки. Например, определение "alias.new =! Gitk -all --not ORIG_HEAD", вызов "git new" эквивалентен запуску команды оболочки "gitk --all --not ORIG_HEAD". Обратите внимание, что команды оболочки будут выполняться из каталога верхнего уровня репозитория, который необязательно может быть текущим каталогом. [...]
То, как я это вижу, - если псевдоним "будет рассматриваться как команда оболочки", когда префикс с восклицательным знаком - зачем мне нужно использовать функцию или sh -c
с аргументами; почему не просто написать мою команду as-is?
Я все еще не знаю ответа - но я думаю, что на самом деле есть небольшая разница в исходе. Вот небольшой тест - выбросьте это в свой .git/config
или ваш ~/.gitconfig
:
[alias]
# ...
ech = "! echo rem: "
shech = "! sh -c 'echo rem:' "
fech = "! f() { echo rem: ; }; f " # must have ; after echo!
echargs = "! echo 0[[\"$0\"]] 1-\"$1\"/ A-"[email protected]"/ "
fechargs = "! f() { echo 0[[\"$0\"]] 1-\"$1\"/ A-"[email protected]"/ ; }; f "
Вот что я запускаю эти псевдонимы:
$ git ech word1 word2
rem: word1 word2
$ git shech word1 word2
rem:
$ git fech word1 word2
rem:
$ git echargs word1 word2
0[[ echo 0[["$0"]] 1-"$1"/ [email protected]/ ]] 1-word1/ A-word1 word2/ word1 word2
$ git fechargs word1 word2
0[[ f() { echo 0[["$0"]] 1-"$1"/ [email protected]/ ; }; f ]] 1-word1/ A-word1 word2/
... или: когда вы используете команду "plain" после !
"as-is" в псевдониме git
, а затем git
автоматически добавляет список аргументов к этой команде! Способ избежать этого, действительно, назвать ваш script как функцию - или как аргумент для sh -c
.
Еще одна интересная вещь (для меня) - это то, что в оболочке script обычно предполагается, что автоматическая переменная $0
будет именем файла script. Но для функции git
alias аргумент $0
представляет собой, в основном, содержимое всей строки, определяющей эту команду (как указано в файле конфигурации).
Вот почему, я думаю, если вы ошибетесь - в нижнем случае это будет избегать внешних двойных кавычек:
[alias]
# ...
fail = ! \"echo 'A' 'B'\"
... - тогда git
завершится с (по крайней мере, для меня) несколько загадочным сообщением:
$ git fail
"echo 'A' 'B'": 1: echo 'A' 'B': not found
fatal: While expanding alias 'fail': ' "echo 'A' 'B'"': No such file or directory
Я думаю, поскольку git
"видел" целую строку как только один аргумент !
- он пытался запустить ее как исполняемый файл; и, соответственно, не удалось найти "echo 'A' 'B'"
в качестве файла.
В любом случае в контексте приведенной выше цитаты git help config
я бы предположил, что более точно указать что-то вроде: "... вызов" git new "эквивалентен запуску команды оболочки" gitk --all --not ORIG_HEAD [email protected] ", где [email protected] аргументы, переданные в псевдоним команды git из командной строки во время выполнения....". Я думаю, что это также объясняет, почему "прямой" подход в OP не работает с позиционными параметрами.