Псевдоним 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 ответов


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

[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 \"\"^ \"\" #"

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

Примечание: 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).

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


Как заявил Drealmer выше:

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

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

git config --глобальный псевдоним.ЛС!компакт-диск "${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 ;

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

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


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

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