Basicamente, eu estou tentando alias:
git files 9fa3
... para executar o comando:
git diff --name-status 9fa3^ 9fa3
mas o git não parece passar parâmetros posicionais para o comando alias. Eu tentei:
[alias]
files = "!git diff --name-status $1^ $1"
files = "!git diff --name-status {1}^ {1}"
... e alguns outros, mas esses não funcionaram.
O caso degenerado seria:
$ git echo_reverse_these_params a b c d e
e d c b a
... como posso fazer isso funcionar?
$1
deve funcionar).Respostas:
A maneira mais óbvia é usar uma função shell:
Um alias sem
!
é tratado como um comando Git; por exemplocommit-all = commit -a
.Com o
!
, ele é executado como seu próprio comando no shell, permitindo que você use uma magia mais forte como esta.UPD
Como os comandos são executados na raiz do repositório, você pode usar a
${GIT_PREFIX}
variável ao se referir aos nomes dos arquivos nos comandosfonte
!
é tratado como um comando Git; por exemplocommit-all = commit -a
. Com o!
, ele é executado como seu próprio comando no shell, permitindo que você use uma magia mais forte como esta.!
será executado na raiz do repositório, portanto, usar caminhos relativos ao chamar seu alias não fornecerá os resultados que você pode esperar.Você também pode fazer referência
sh
diretamente (em vez de criar uma função):(Observe o traço no final da linha - você precisará disso.)
fonte
sh
, já que ele é um shell e está disponível na grande maioria dos sistemas. O uso do shell padrão funciona apenas se o comando funcionar como escrito para todos os shells.--
a-
como é mais familiar e menos propensos a stdin acidentalmente média em algum ponto. ( "Um argumento - é equivalente a -" em bash (1) é ungoogleable)sh -c
) também é desnecessário. Veja minha resposta para uma alternativa.O alias que você está procurando é:
Com validação de argumento:
A final
#
é importante - impede que todos os argumentos fornecidos pelo usuário sejam processados pelo shell (os comenta).Nota:
git
coloca todos os argumentos fornecidos pelo usuário no final da linha de comando. Para ver isso em ação, tente:GIT_TRACE=2 git files a b c d
As aspas escapadas (devido ao aninhamento) são importantes para nomes de arquivos que contêm espaços ou
"; rm -rf --no-preserve-root /;
)fonte
!
já implicash -c
(mostrado ao anexarGIT_TRACE=2
), portanto não há necessidade de executar outro sub-shell. Que problemas você vê nos casos mais complicados?fp = "! 1=${1:-$(git headBranch)}; 2=${2:-up}; git fetch -fu $2 pull/$1/head:$1; git checkout $1; git branch -u $2 #"
. Isso funciona muito bem sem as duas primeiras instruções, mas cai se você as usar. (Eu também tenhoheadBranch = symbolic-ref --short HEAD
).fp = "! a=${1:-$(git headBranch)}; b=${2:-up}; git fetch -fu $b pull/$a/head:$a; git checkout $a; git branch -u $b #"
."
aspas são necessárias?Use GIT_TRACE = 1 descrito na página de manual do git para tornar transparente o processamento do alias:
Seus comandos originais funcionam com a versão 1.8.3.4 do git (o Eimantas notou que isso foi alterado na 1.8.2.1).
As opções
sh -c '..' --
ef() {..}; f
manipulam de maneira limpa os parâmetros "$ @" de diferentes maneiras (veja em GIT_TRACE). Anexar "#" a um alias também permitiria parâmetros posicionais sem sair dos finais.fonte
files = "!git diff --name-status $1^ $1 #"
files = "!git diff --name-status $1^"
Como afirmado por Drealmer acima :
GIT_PREFIX
sendo definido pelo git para o subdiretório em que você está, você pode contornar isso alterando primeiro o diretório:fonte
cd ${GIT_PREFIX:-.} &&.
" (fonte: stackoverflow.com/a/21929373/266309 )!cd "${GIT_PREFIX:-.}" && ls -al
Eu queria fazer isso com um alias que faz isso:
No final, criei um script de shell chamado git-m que tem este conteúdo:
Isso tem o benefício de ser muito mais legível porque está em várias linhas. Além disso, eu gosto de poder chamar o bash com
-x
eset -e
. Você provavelmente pode fazer tudo isso como um apelido, mas seria super feio e difícil de manter.Como o arquivo é nomeado,
git-m
você pode executá-lo assim:git m foo bar
fonte
'!f() { : git branch ; ... }; f'
e ele completará automaticamente o alias como um ramo que é super útil..bashrc
arquivo que eu forneço. Mas acho que não mudei a maneira como preencho automaticamente os argumentos para um script, tanto quanto o próprio script, e seria apenas durante o desenvolvimento.Apenas esbarrei em algo semelhante; espero que esteja tudo bem em publicar minhas anotações. Uma coisa que me confunde sobre
git
aliases com argumentos, provavelmente vem dogit help config
(eu tenho a versão 1.7.9.5 do git):Do jeito que eu vejo - se um apelido "será tratado como um comando de shell" quando prefixado com ponto de exclamação - por que eu precisaria usar uma função ou
sh -c
com argumentos; por que não apenas escrever meu comando como está?Ainda não sei a resposta - mas acho que, na verdade, há uma pequena diferença no resultado. Aqui está um pequeno teste - jogue isso no seu
.git/config
ou no seu~/.gitconfig
:Aqui está o que eu recebo executando esses aliases:
... ou: quando você estiver usando um comando "simples" após o
!
"no estado em que está" em umgit
alias -git
anexará automaticamente a lista de argumentos a esse comando! Uma maneira de evitá-lo é chamar seu script como uma função - ou como argumentosh -c
.Outra coisa interessante aqui (para mim) é que, em um script de shell, normalmente se espera que a variável automática
$0
seja o nome do arquivo do script. Mas para umagit
função de alias, o$0
argumento é, basicamente, o conteúdo de toda a cadeia que especifica esse comando (conforme digitado no arquivo de configuração).Por isso, eu acho, se você citar incorretamente - no caso abaixo, isso estaria escapando das aspas duplas externas:
... - então
git
falharia com (pelo menos para mim) a mensagem um tanto enigmática:Eu acho que, uma vez que
git
"via" uma string inteira como apenas um argumento para!
- tentava executá-la como um arquivo executável; e correspondentemente falhou ao encontrar"echo 'A' 'B'"
como um arquivo.De qualquer forma, no contexto da
git help config
citação acima, eu especularia que é mais preciso afirmar algo como: " ... a invocação" git new "é equivalente a executar o comando shell" gitk --all --not ORIG_HEAD $ @ ", onde $ @ são os argumentos passados para o alias do comando git na linha de comando no tempo de execução. ... ". Eu acho que isso também explicaria por que a abordagem "direta" no OP não funciona com parâmetros posicionais.fonte
fail
está tentando executar um comando chamado "eco 'A' 'B" (ou seja, 10 caracteres). Mesmo erro desh -c "'echo a b'"
e mesma causa, muitas camadas de citações