Git alias z parametrami pozycyjnymi

W zasadzie staram się:

git files 9fa3

... Aby wykonać polecenie:

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

Ale wydaje się, że git nie przekazuje parametrów pozycyjnych komendzie alias. Próbowałem:

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

...i kilka innych, ale te nie zadziałały.

Przypadek degenerata to:

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

...Jak mogę to zrobić?

Author: user400575, 2010-07-23

7 answers

Najbardziej oczywistym sposobem jest użycie funkcji powłoki:

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

Alias Bez {[1] } jest traktowany jako polecenie Git, np. commit-all = commit -a.

Z !, jest uruchamiany jako własne polecenie w powłoce, pozwalając Ci używać silniejszej magii, takiej jak ta.

UPD
Ponieważ polecenia są wykonywane w katalogu głównym repozytorium, możesz użyć zmiennej ${GIT_PREFIX} w odniesieniu do nazw plików w poleceniach

 306
Author: Cascabel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-04 13:20:24

Możesz również odwołać się bezpośrednio do sh (zamiast tworzyć funkcję):

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

(zwróć uwagę na myślnik na końcu linii, będziesz tego potrzebował.)

 82
Author: mipadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-09 09:39:55

Alias, którego szukasz to:

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

Z potwierdzeniem argumentu:

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

Finał # jest ważne - zapobiega przetwarzaniu przez powłokę wszystkich argumentów dostarczonych przez użytkownika (komentuje je).

Uwaga: git umieszcza wszystkie argumenty dostarczone przez użytkownika na końcu wiersza poleceń. Aby zobaczyć to w akcji, spróbuj: GIT_TRACE=2 git files a b c d

Znaki ucieczki (ze względu na zagnieżdżanie) cudzysłowy są ważne dla nazw plików zawierających spacje lub "; rm -rf --no-preserve-root /;)

 51
Author: Tom Hale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-09 10:41:57

Użyj GIT_TRACE = 1 opisanego na stronie podręcznika Gita, aby przeźroczyć przetwarzanie aliasów:

$ 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

Twoje oryginalne polecenia działają z Gitem w wersji 1.8.3.4(Eimantas zauważył to w wersji 1.8.2.1).

Opcje sh -c '..' -- i f() {..}; f obsługują parametry "$ @ " na różne sposoby (zobacz z GIT_TRACE). Dodanie " # " do aliasu umożliwi również ustawienie parametrów pozycyjnych bez opuszczania końcowych.

 21
Author: bsb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-26 01:27:01

Jak stwierdził Drealmer powyżej:

" uważaj ! będzie działać w katalogu głównym repozytorium, więc użycie ścieżek względnych podczas wywoływania aliasu nie da oczekiwanych wyników. - Drealmer Aug 8 '13 at 16: 28"

GIT_PREFIX będąc ustawionym przez git do podkatalogu, w którym się znajdujesz, możesz to obejść, zmieniając najpierw katalog:

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

 16
Author: Pierre-Olivier Vares,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-05 08:57:20

Chciałem to zrobić z aliasem, który robi to:

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

W końcu stworzyłem skrypt powłoki o nazwie git-m , który ma taką zawartość:

#!/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;

To ma tę zaletę, że jest dużo bardziej czytelne, ponieważ jest na wielu liniach. Poza tym lubię dzwonić do Basha z -x i set -e. Prawdopodobnie możesz zrobić to wszystko jako alias, ale byłoby to bardzo brzydkie i trudne do utrzymania.

Ponieważ plik ma nazwę git-m można go uruchomić jak to: git m foo bar

 8
Author: Daniel Kaplan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-21 04:09:34

Wpadłem na coś podobnego; mam nadzieję, że mogę publikować moje notatki. Jedna rzecz, która mnie myli o git aliasy z argumentami, prawdopodobnie pochodzi z git help config (mam git w wersji 1.7.9.5):

Jeśli rozszerzenie aliasu jest poprzedzone wykrzyknikiem, będzie traktowane jako polecenie powłoki. Na przykład definiowanie " alias.nowy = !gitk --all --not ORIG_HEAD", wywołanie "Git new" jest równoznaczne z uruchomieniem polecenia powłoki "gitk -- all -- not ORIG_HEAD". Zauważ, że polecenia powłoki będą wykonywane z katalogu najwyższego poziomu repozytorium, który niekoniecznie musi być bieżącym katalogiem. [...]

Sposób, w jaki to widzę - jeśli alias "będzie traktowany jako polecenie powłoki", gdy będzie poprzedzony wykrzyknikiem - dlaczego miałbym używać funkcji lub sh -c z argumentami; dlaczego po prostu nie napisać mojego polecenia jako-is?

Nadal nie znam odpowiedzi - ale myślę, że faktycznie jest niewielka różnica w wyniku. Oto mały test-rzut to w twoim .git/config lub twoim ~/.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 "

Oto co dostaję z tymi aliasami:

$ 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/

... albo: gdy używasz polecenia "plain" po ! "as-is" w aliasie git - wtedy git automatycznie dołącza listę argumentów do tego polecenia! Sposobem na uniknięcie tego jest wywołanie skryptu jako funkcji-lub jako argumentu do sh -c.

Kolejną ciekawą rzeczą (dla mnie) jest to, że w skrypcie powłoki typowo oczekuje się zmiennej automatycznej $0 być nazwą pliku skryptu. Ale dla funkcji git alias, argument $0 jest zasadniczo zawartością całego ciągu znaków określającego tę komendę (wpisanego w pliku konfiguracyjnym).

Dlatego, myślę, że jeśli zdarzy ci się źle cytować - w poniższym przypadku, byłoby to unikanie zewnętrznych podwójnych cudzysłowów: {]}

[alias]
  # ...
  fail = ! \"echo 'A' 'B'\"

... - wtedy git zawiedzie (przynajmniej dla mnie) nieco tajemnicza wiadomość:

$ git fail
 "echo 'A' 'B'": 1: echo 'A' 'B': not found
fatal: While expanding alias 'fail': ' "echo 'A' 'B'"': No such file or directory

Myślę, że od git "widziałem" cały string jako tylko jeden argument ! - próbował uruchomić go jako plik wykonywalny; i odpowiednio nie udało mu się znaleźć "echo 'A' 'B'" jako plik.

W każdym razie, w kontekście git help config cytatu powyżej, spekulowałbym, że bardziej trafne jest stwierdzenie czegoś w stylu: "{36]}... wywołanie " Git new "jest równoznaczne z uruchomieniem polecenia powłoki" gitk --all --not ORIG_HEAD$@", gdzie $@ są argumentami przekazywanymi do aliasu polecenia git z linii poleceń podczas wykonywania. ... ". Myślę, że tak. wyjaśnij również, dlaczego podejście "bezpośrednie" w OP nie działa z parametrami pozycyjnymi.

 4
Author: sdaau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-22 20:10:40