Git псевдоним с позиционными параметрами - PullRequest
232 голосов
/ 23 июля 2010

Обычно я пытаюсь использовать псевдоним:

git files 9fa3

... для выполнения команды:

git diff --name-status 9fa3^ 9fa3

, но git не передает позиционные параметры псевдонимукоманда.Я пытался:

[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

...Как я могу сделать эту работу?

Ответы [ 7 ]

335 голосов
/ 24 июля 2010

Самый очевидный способ - использовать функцию оболочки:

[alias]
    files = "!f() { git diff --name-status \"$1^\" \"$1\"; }; f"

Псевдоним без ! обрабатывается как команда Git; например commit-all = commit -a.

С ! он запускается как отдельная команда в оболочке, позволяя вам использовать более сильную магию, подобную этой.

UPD
Поскольку команды выполняются в корне хранилища, вы можете использовать переменную ${GIT_PREFIX} при обращении к именам файлов в командах

88 голосов
/ 25 июля 2010

Вы также можете ссылаться на sh напрямую (вместо создания функции):

[alias]
        files = !sh -c 'git diff --name-status $1^ $1' -

(Обратите внимание на черту в конце строки - она ​​вам понадобится.)

69 голосов
/ 16 сентября 2016

Псевдоним, который вы ищете:

files = "!git diff --name-status \"$1\"^ \"$1\" #"

С проверкой аргумента:

files = "!cd -- \"${GIT_PREFIX:-.}\" && [ x$# != x1 ] && echo commit-ish required >&2 || git diff --name-status \"$1\"^ \"$1\" #"

Значение final # важно - оно предотвращает обработку всех предоставленных пользователем аргументов оболочкой (она их комментирует).

Примечание: git помещает все предоставленные пользователем аргументы в конец командной строки. Чтобы увидеть это в действии, попробуйте: GIT_TRACE=2 git files a b c d

Экранированные (из-за вложенности) кавычки важны для имен файлов, содержащих пробелы или "; rm -rf --no-preserve-root /;)

24 голосов
/ 26 августа 2013

Используйте GIT_TRACE = 1, описанный на странице руководства git, чтобы сделать обработку псевдонимов прозрачной:

$ 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 "$@"' '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 оба по-разному обрабатывают параметры "$ @" (см. С GIT_TRACE). Добавление «#» к псевдониму также позволило бы позиционные параметры, не оставляя завершающих.

16 голосов
/ 26 февраля 2014

Как указано Дреалмером выше :

«Будь осторожен,!будет выполняться в корне хранилища, поэтому использование относительных путей при вызове псевдонима не даст ожидаемых результатов.- Drealmer 8 августа '13 в 16:28 »

GIT_PREFIX будучи установленным git в подкаталог, в котором вы находитесь, вы можете обойти это, сначала изменив каталог:

git config --global alias.ls '! cd "$ {GIT_PREFIX: -.}"; ls -al'

8 голосов
/ 21 июня 2014

Я хотел сделать это с псевдонимом, который делает это:

git checkout $1;
git merge --ff-only $2;
git branch -d $2;

В конце я создал сценарий оболочки с именем 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

4 голосов
/ 23 апреля 2013

просто наткнулся на нечто подобное;надеюсь, что все в порядке, чтобы опубликовать мои заметки.Одна вещь, которая смущает меня относительно 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 с аргументами;почему бы просто не написать мою команду как есть?

Я до сих пор не знаю ответа - но я думаю, что на самом деле есть небольшая разница в результатах.Вот небольшой тест - добавьте это в свой .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-"$@"/ "
  fechargs = "! f() { echo 0[[\"$0\"]] 1-\"$1\"/ A-"$@"/ ; }; 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"/ A-$@/ ]] 1-word1/ A-word1 word2/ word1 word2

$ git fechargs word1 word2
0[[ f() { echo 0[["$0"]] 1-"$1"/ A-$@/ ; }; f ]] 1-word1/ A-word1 word2/

... или:когда вы используете "обычную" команду после ! "как есть" в псевдониме git - тогда git автоматически добавляет список аргументов к этой команде!Способ избежать этого - вызвать ваш скрипт как функцию или как аргумент sh -c.

Еще одна интересная вещь (для меня) заключается в том, что в сценарии оболочки обычно ожидается, что автоматическая переменная $0 будет именем файла сценария.Но для псевдонима git аргумент $0 - это, по сути, содержимое строки whole , определяющей эту команду (как указано в файле конфигурации).

Вот почему, я полагаю, если вы ошибетесь в кавычках - в приведенном ниже случае это будет экранировать двойные внешние кавычки:

[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 $ @", где $ @ - это аргументы, передаваемые псевдониму команды git из командной строки во время выполнения. ...".Думаю, это также объясняет, почему «прямой» подход в OP не работает с позиционными параметрами.

...