Псевдоним Git с позиционными параметрами


в основном я пытаюсь псевдоним:

git files 9fa3

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

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

но git, похоже, не передает позиционные параметры команде alias. Я пробовал:

[alias]
    files = "!git diff --name-status ^ "
    files = "!git diff --name-status {1}^ {1}"

...и еще несколько других, но они не сработали.

вырожденный случай будет:

$ git echo_reverse_these_params a b c d e
e d c b a

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

7 209

7 ответов:

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

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

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

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

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

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

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

(обратите внимание на тире в конце строки-вам нужно что.)

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

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

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

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

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

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

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

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

$ git config alias.files
!git diff --name-status ^ 
$ GIT_TRACE=1 git files 1d49ec0
trace: exec: 'git-files' '1d49ec0'
trace: run_command: 'git-files' '1d49ec0'
trace: run_command: 'git diff --name-status ^ ' '1d49ec0'
trace: exec: '/bin/sh' '-c' 'git diff --name-status ^  "$@"' 'git diff --name-status ^ ' '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).

The sh -c '..' -- и f() {..}; f параметры оба чисто обрабатывать параметры "$ @ " по-разному (см. С GIT_TRACE). Добавление " # "к псевдониму также позволит использовать позиционные параметры, не выходя из конечных.

Как заявил Дреалмер выше:

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

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

git config --global alias.ls '!компакт-диск "${GIT_PREFIX:-.}"; ls-al'

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

git checkout ;
git merge --ff-only ;
git branch -d ;

в конце концов, я создал скрипт с именем 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 ;
git merge --ff-only ;
git branch -d ;

это имеет то преимущество, что он много более разборчиво, потому что это на нескольких линиях. Плюс мне нравится быть в состоянии позвонить Баш с -x и set -e. Вы, вероятно, можете сделать все это как псевдоним, но это было бы супер уродливо и трудно поддерживать.

потому что файл называется git-m вы можете запустить его примерно так: git m foo bar

просто наткнулся на что-то подобное; надеюсь, что это нормально, чтобы опубликовать мои заметки. Одна вещь, которая меня смущает git псевдонимы с аргументами, вероятно, происходит от git help config (у меня есть git версии 1.7.9.5):

если расширение псевдонима сопровождается восклицательным знаком, оно будет рассматриваться как команда оболочки. Например, определение "псевдоним.новый = !gitk --all --not ORIG_HEAD", вызов "git new" эквивалентен выполнению команды оболочки - ГИТ ...все ...нет 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[[\"\"]] 1-\"\"/ A-"$@"/ "
  fechargs = "! f() { echo 0[[\"\"]] 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[[""]] 1-""/ A-$@/ ]] 1-word1/ A-word1 word2/ word1 word2

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

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

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

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

[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 из командной строки во время выполнения. ...". Я думаю, что это также объясняет, почему "прямой" подход в ОП не работает с позиционными параметрами.