Alias ​​do Git - vários comandos e parâmetros

182

Estou tentando criar um alias que usa vários comandos Git e parâmetros posicionais. Existem páginas Stackoverflow para cada uma, e parece dolorosamente óbvio fazer as duas coisas, mas estou tendo problemas.

Como exemplo, quero mudar para o ramo foo e executar um status. Então, no meu .gitconfig, eu tenho:

  [alias] 
     chs = !sh -c 'git checkout $0 && git status'

o que não funciona. Considerando que algo assim vai funcionar.

chs = !sh -c 'git checkout $0'

echoes = !sh -c 'echo hi && echo bye'

Qualquer insight seria apreciado.

Stella
fonte
Meu alias: git config --global alias.go '! Git commit -a && git pull --rebase && git push && git status'. Nota: use aspas simples.
Marcus Becker

Respostas:

157

Isso funcionará (testado com zsh e bash):

[alias] chs = !git checkout $1 && git status
Olivier Verdier
fonte
1
Não, não vai. Git vai se transformar git chs fooemgit checkout && git status foo
Lily Ballard
24
Interessante, o git, na verdade, preenche as variáveis ​​posicionais agora nos aliases do shell. Mas ainda está quebrado, porque também os usa como argumentos. Um alias de echo $1 && echo done, quando chamado com o argumento 'foo', produzirá "foo" e "done foo".
Lily Ballard
7
Qual é o ponto de exclamação anterior na primeira chamada de git?
Elias Lynn
21
@ElijahLynn: Em um alias do git, um !meio principal passa a coisa toda para o shell. Caso contrário, ele assume que você está tentando executar outro comando git e o passa como argumentos para o gitbinário.
Lily Ballard
2
@Brondahl Clever. Eu recomendo em ;:vez de && :embora. E isso também funciona bem no unix.
Lily Ballard
82

Isso tem como alvo o Windows batch / msysgit bash; pode não funcionar em outros ambientes.

Como Olivier Verdier e Lily Ballard disseram

[alias] chs = !git checkout $1 && git status

quase funciona, mas fornece uma inserção extra espúria do argumento ...

git chs demo -> git checkout demo && git status demo

Mas se você adicionar && :ao final do seu alias, o argumento falso será consumido em uma tag de localização.

assim

[alias] chs = !git checkout $1 && git status && :

dá a saída correta ... git chs demo -> git checkout demo && git status

Brondahl
fonte
9
O && :é ouro e faz com que esta solução funcione para comandos em que o argumento extra seria problemático.
Clay
3
@Clay (ou qualquer outra pessoa) - Alguém poderia explicar aos desafiados pelo BASH o que && :faz?
23816 Justin MorganJan
7
@JustinMorgan && significa que se o comando anterior fizer 0 (êxito), execute o comando após &&. ':', os dois pontos, é um comando interno do shell, que não faz nada além de expandir argumentos e executar redirecionamentos e retornar o status 0. Aqui estão alguns usos: 1. a=123;$aerros, mas a=123; : $anão. 2. : > hello.txtesvazia hello.txt. 3. if [ "$a" = "hello" ];then : ;firoda bem, mas erros sem ':'. É como passem python. 4. : this is a comment, os dois pontos seguidos por espaço funcionam como #em uma linha de comentário.
precisa saber é o seguinte
2
este é como um hack ... git deve aceitar o modo de comando múltipla
kchoi
1
Obrigado @ElpieKay pela explicação. Meu alias do git local para um projeto era co = !git checkout public/compiled && git checkout $1e, quando o faria, recebia git co mastera mensagem error: pathspec 'master' did not match any file(s) known to git.. Não achei que essa resposta fosse útil para mim, porque a primeira coisa que menciona é o Windows e eu estou no Linux. Mas você explicou o porquê.
Tyler Collier
73

Você pode definir uma função shell.

[alias] chs = "!f(){ git checkout \"$1\" && git status; };f"
Lily Ballard
fonte
Vi isso em outra página de stackoverflow, mas meu terminal cygwin diz que a função não é reconhecida quando tento executá-la.
Stella
@ Stella: Deixei uma citação de fechamento lá que não é útil nesta sintaxe do arquivo de configuração. Verifique se você não o possui.
Lily Ballard
2
Uau ... Infelizmente, isso tudo foi um problema de versão. Eu estava usando o Git 1.7.3 e nenhum desses métodos funcionou. Eu atualizei para 1.7.6 e pronto, tudo funcionou. Obrigado rapazes!
Stella
5
se estiver usando o Windows eu acho que você tem que cercam a definição da função shell com aspas"
drzaus
4
A resposta de Olivier não funcionou para mim usando parâmetros (OSX). Isso funcionou perfeitamente.
Ohad Schneider
25

Consegui criar aliases git de várias linhas e bastante complexos. Eles funcionam bem no Windows, mas presumo que também funcionariam em outros lugares, por exemplo:

safereset = "!f() { \
                trap 'echo ERROR: Operation failed; return' ERR; \
                echo Making sure there are no changes...; \
                last_status=$(git status --porcelain);\
                if [[ $last_status != \"\" ]]; then\
                    echo There are dirty files:;\
                    echo \"$last_status\";\
                    echo;\
                    echo -n \"Enter Y if you would like to DISCARD these changes or W to commit them as WIP: \";\
                    read dirty_operation;\
                    if [ \"$dirty_operation\" == \"Y\" ]; then \
                        echo Resetting...;\
                        git reset --hard;\
                    elif [ \"$dirty_operation\" == \"W\" ]; then\
                        echo Comitting WIP...;\
                        git commit -a --message='WIP' > /dev/null && echo WIP Comitted;\
                    else\
                        echo Operation cancelled;\
                        exit 1;\
                    fi;\
                fi;\
            }; \
            f"

Eu escrevi um post e tenho mais alguns exemplos aqui .

VitalyB
fonte
2
uma melhoria para isso seria adicionar !f() { : resetpara obter conclusões do comando reset github.com/git/git/blob/master/contrib/completion/…
um usuário
Bom trabalho! Em que licença esse artigo é publicado? Você se importaria se eu traduzisse partes dele para o StackOverflow em russo?
precisa
@NickVolynkin Desculpe pela resposta tardia. Obrigado e, claro, vá em frente :)
VitalyB
22
[alias]
chs = !git branch && git status
FractalSpace
fonte
8
Para que serve !?
AutonomousApps
1
Eu não consegui encontrar o doc para o !mas, tanto quanto eu posso ver o git por padrão assumirá que o alias é um comando git, então t = statusfuncionará. No entanto, se você tentar t = git status, não funcionará (dirá o comando "git" não encontrado). Para que, onde ele !entra, ele diz para executar o comando como se fosse um shell, e normalmente você precisa disso quando possui vários comandos git por alias, para que você possa ter, t = !git status && git logpor exemplo, e ele funcionará.
laurent
Aqui está uma pergunta do StackOverflow que lida com pontos de exclamação (!) Nos aliases do Git: stackoverflow.com/questions/21083933/… .
Jacob Lockard 8/07
6

Tente este:

[alias]
    chs = "!sh -c 'git checkout \"$0\" && git status'"

Chame assim: git chs master

brocksamson
fonte
6

É possível ter um alias de git de várias \linhas anexando ao final de cada linha.

[alias] 
   chs = "!git checkout $1 \ 
          ; git status     \
         "
gmarik
fonte
2
Obrigado! Na verdade, não tive nenhum problema em usar "!git fetch --prune --all; git pull --rebase upstream master; git push origin master"meu apelido.
Droogans 09/07/19
3

O problema aqui é que os parâmetros posicionais parecem estar sendo enviados para o comando shell duas vezes (a partir do git 1.9.2). Para ver o que quero dizer, tente o seguinte:

[alias]
  test = !git echo $*

Então faça git test this is my testing string. Você deve observar a seguinte saída (últimas duas linhas editadas aqui para maior clareza):

03:41:24 (release) ~/Projects/iOS$ git test this is my testing string
this is my testing string this is my testing string
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
          #1                         #2

Uma maneira de contornar isso seria:

[alias]
  chs = !git checkout $1 && git status && git echo x >/dev/null

Isso consumirá o parâmetro posicional extra à medida que for aplicado ao último comando de eco e não terá efeito nos resultados.

Ben Collins
fonte