Konum parametrelerine sahip git takma adı


261

Temelde takma ad vermeye çalışıyorum:

git files 9fa3

... komutu çalıştırmak için:

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

ancak git, alias komutuna konumsal parametreler geçiriyor gibi görünmüyor. Denedim:

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

... ve birkaç kişi daha, ama bunlar işe yaramadı.

Dejenere vaka:

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

... bu işi nasıl yapabilirim?


17
Git 1.8.2.1'de bunu kabuk fonksiyonu olmadan yapabileceğinizi unutmayın (orijinal yaklaşımınız $1işe yaramalıdır).
Eimantas

7
@Eimantas Bir cevapta ayrıntılı olarak düşünür müsünüz? Benim için işe yaramıyor ve bununla ilgili herhangi bir belge bulamıyorum.
pavon

@Eimantas sürüm notlarında bununla ilgili hiçbir şey yok .
Knu

1
Git 2.11'de herhangi bir parıltı olmadan kabuk komutlarını argümanlarla çalıştırabildiğimi doğrulayabilirim.
anarcat

Yanıtlar:


365

En belirgin yol bir kabuk işlevi kullanmaktır:

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

Bulunmayan bir takma ad !Git komutu olarak kabul edilir; örn commit-all = commit -a.

İle, !kabukta kendi komutu olarak çalıştırılır ve böyle daha güçlü bir sihir kullanmanıza izin verir.

UPD
Komutlar havuzun kökünde yürütüldüğünden, ${GIT_PREFIX}komutlardaki dosya adlarına başvururken değişken kullanabilirsiniz


8
Teşekkürler, bu tam olarak doğru görünüyor: [takma ad] dosyaları = "! F () {echo $ 3 $ 2 $ 1;}; f"; $ git files abc => cba
user400575

1
@ KohányiRóbert: Bu aslında bir kabuk senaryosu sorusu değil; bu git config özel bir. Bulunmayan bir takma ad !Git komutu olarak kabul edilir; örn commit-all = commit -a. İle, !kabukta kendi komutu olarak çalıştırılır ve böyle daha güçlü bir sihir kullanmanıza izin verir.
Cascabel

40
Dikkatli olun, !deponun kökünde çalışır, bu nedenle takma adınızı çağırırken göreli yollar kullanmak beklediğiniz sonuçları vermez.
Drealmer

4
@RobertDailey Kırmaz, uygulamaz. Ekleme hakkında bilgi için stackoverflow.com/questions/342969/… adresine bakın .
Cascabel

3
Not : Bu (genel olarak tehlikeli olan) argümanları alıntılamaz. Ayrıca, bir işlev gerekli değildir. Bkz Cevabımı daha açıklama için.
Tom Hale

96

Ayrıca shdoğrudan başvuruda bulunabilirsiniz (işlev oluşturmak yerine):

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

(Çizginin sonundaki çizgiye dikkat edin - buna ihtiyacınız olacak.)


8
Komutu paylaşıyorsanız, muhtemelen kullanmak istersiniz sh, çünkü bu kendi içinde bir kabuktur ve sistemlerin büyük çoğunluğunda mevcuttur. Varsayılan kabuğun kullanılması, yalnızca komut tüm kabuklar için yazıldığı gibi çalışıyorsa çalışır.
nomothetis

12
Ben tercih --etmek -bir noktada yanlışlıkla ortalama stdin'e daha tanıdık ve daha az olasıdır olarak. (Bash (1) 'deki "- argümanı - ile eşdeğerdir" kabul edilemez)
bsb


5
'-' sonunun tam anlamı nedir ve nerede belgelenir?
Zitrax

5
Not : Bu (genel olarak tehlikeli olan) argümanları alıntılamaz. Alt kabuk (ile sh -c) oluşturmak da gereksizdir. Bir alternatif için cevabımı görün .
Tom Hale

81

Aradığınız takma ad:

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

Bağımsız değişken doğrulaması ile:

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

nihai# önemlidir - kabuk (onları dışarı yorumlar) tarafından işlenmekte olan tüm kullanıcı tarafından sağlanan argümanlar önler.

Not: git kullanıcı tarafından sağlanan tüm bağımsız değişkenleri komut satırının sonuna yerleştirir. Bunu çalışırken görmek için şunu deneyin:GIT_TRACE=2 git files a b c d

Kaçan (iç içe geçme nedeniyle) tırnak işaretleri boşluk içeren dosya adları için önemlidir veya "; rm -rf --no-preserve-root /;)


En basit durumlar için bu doğru cevaptır, gerçekten bir fonksiyona veya sh -c'ye sararak karmaşıklaştırmaya gerek yoktur.
Ed Randall

4
Evet, !zaten ima ediyor sh -c(hazırlarken gösterilir GIT_TRACE=2), başka bir alt kabuk çalıştırmanıza gerek yoktur. Daha karmaşık durumlarda hangi sorunları görüyorsunuz?
Tom Hale

Varsayılan bağımsız değişkenleri ayarlamak istiyorsanız bu işe yarar mı? mesela ben Github PR getirmek için bunu yapmak istiyorum: fp = "! 1=${1:-$(git headBranch)}; 2=${2:-up}; git fetch -fu $2 pull/$1/head:$1; git checkout $1; git branch -u $2 #". Bu, ilk iki ifade olmadan harika çalışır, ancak bunları kullanırsanız düşer. (Bende var headBranch = symbolic-ref --short HEAD).
gib

2
Bu gayet bile, yeni params ayarlarsanız çalıştığını, bunu çalıştı: fp = "! a=${1:-$(git headBranch)}; b=${2:-up}; git fetch -fu $b pull/$a/head:$a; git checkout $a; git branch -u $b #".
gib

"tırnak işaretleri neden gereklidir?
Eugen Konkov

28

Takma ad işlemeyi saydam hale getirmek için git man sayfasında açıklanan GIT_TRACE = 1 kullanın:

$ 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

Orijinal komutlarınız git sürüm 1.8.3.4 ile çalışır (Eimantas bunun 1.8.2.1'de değiştiğini kaydetmiştir).

sh -c '..' --Ve f() {..}; fseçenekleri hem temiz "$ @" idare farklı şekillerde parametrelerini (GIT_TRACE ile bakınız). Bir takma ada "#" eklemek, sondaki parametreleri bırakmadan konum parametrelerine de izin verir.


1
açıklamalar için teşekkürler: bu komutlar tavsiye, benim için orijinal sorun üzerinde çalışır:files = "!git diff --name-status $1^ $1 #" files = "!git diff --name-status $1^"
user2291758

20

Yukarıda Drealmer tarafından belirtildiği gibi :

" Dikkatli ol, ! deponun kökünde çalışır, bu nedenle takma adınızı çağırırken göreli yollar kullanmak beklediğiniz sonuçları vermez. - Drealmer 8 '13 at 16:28 »

GIT_PREFIX git tarafından bulunduğunuz alt dizine ayarlandığında, önce dizini değiştirerek bunu atlatabilirsiniz:

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


Ben de bu konuda sorun yaşıyorum (komutlar deponun kökünde çalıştırılıyor) ama bu çözüm bir şey yapmak gibi görünmüyor. (Eğer
önemliyse,

Hata! Git takma ad, yaptığım bir takma ad.
Pierre-Olivier Vares

(git 1.8.2'den beri) git config - set alias.alias = '! git config - küresel takma ad. 1 $ "2 $"
Pierre-Olivier Vares

Benim için sonuçlanan budur: "Git takma adlarınızı (kabuk komutlarını çalıştıran ve doğru cd ${GIT_PREFIX:-.} &&.
pwd'ye

Bunu alıntı yap. !cd "${GIT_PREFIX:-.}" && ls -al
mirabilos

8

Bunu bunu yapan bir takma adla yapmak istedim:

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

Sonunda , bu içeriğe sahip git-m adlı bir kabuk komut dosyası oluşturdum :

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

Bunun çok daha okunaklı olması avantajı vardır, çünkü birden fazla satırdadır. Ayrıca bash ile -xveset -e . Muhtemelen tüm bunları bir takma ad olarak yapabilirsiniz, ancak süper çirkin ve bakımı zor olurdu.

Dosya adlandırıldığından, dosyayı şu git-mşekilde çalıştırabilirsiniz:git m foo bar


1
Ben de bundan çok hoşlanıyorum, ama bu yaklaşımla istediğim otomatik tamamlamayı nasıl kullanacağımı anlayamadım. '!f() { : git branch ; ... }; f'Takma adlarda bunu yapabilirsiniz: ve takma adı süper kullanışlı bir dal olarak otomatik olarak tamamlar.
Hassek

Evet, sanırım önemsiz olmayan şeyleri yol üzerinde bireysel komut dosyaları olarak yapmayı tercih ediyorum. Aşağı tarafı ise evet, referanslar gibi şeylerin otomatik tamamlanmasını kaybedersiniz. Kendi otomatik tamamlamanızı manuel olarak yapılandırarak bunu düzeltebilirsiniz. Yine de, bir komut dosyasını yoldaki bir klasöre bırakabilmenizi seviyorum ve çalışmaya başlayacak, ancak otomatik tamamlama için 'yüklemeniz' gerekiyor, bu yüzden genellikle benim .bashrckaynak dosyamda. Ama betiğin kendisi kadar argümanları otomatik olarak nasıl tamamladığımı değiştirdiğimi sanmıyorum ve bu sadece geliştirme sırasında olurdu.
thecoshman

4

Sadece benzer bir şeye çarptı; Umarım notlarımı göndermem tamamdır. Beni gittakma adlarla takma adlar hakkında git help configşaşırtan bir şey , muhtemelen (Git sürüm 1.7.9.5 var):

Takma ad genişletmesinin önüne bir ünlem işareti gelirse, kabuk komutu olarak değerlendirilir. Örneğin, "alias.new =! Gitk --all - ORIG_HEAD değil" tanımlandığında, "git new" çağrısı, "gitk --all --not ORIG_HEAD" kabuk komutunu çalıştırmaya eşdeğerdir. Kabuk komutlarının, bir deponun en üst düzey dizininden yürütüldüğünü ve bu dizinin geçerli dizin olmayabilir. [...]

Gördüğüm şekilde - bir takma ad "ünlem işareti ile ön ekli olduğunda" bir kabuk komutu olarak değerlendirilecekse "- neden bir işlev veya sh -cbağımsız değişkenler kullanmam gerekiyor? neden sadece komutumu olduğu gibi yazmıyorsun?

Hala cevabı bilmiyorum - ama bence sonuçta ufak bir fark var. İşte küçük bir test - bunu kendinize .git/configveya kendinize atın ~/.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 "

İşte bu takma adları çalıştırmak olsun:

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

... ya da: !bir gittakma gitadda "olduğu gibi" sonrasında bir "düz" komut kullandığınızda - argümanlar listesini otomatik olarak bu komuta ekler! Bundan kaçınmanın bir yolu, betiğinizi bir işlev ya da argüman olarak çağırmaktır sh -c.

Burada (benim için) bir başka ilginç şey, bir kabuk komut dosyasında, tipik olarak otomatik değişkenin $0komut dosyasının dosya adı olmasını beklemesidir . Ancak bir gitdiğer ad işlevi için, $0bağımsız değişken, temelde, bu komutu belirten tüm dizinin içeriğidir ( yapılandırma dosyasına girildiği gibi).

Bu nedenle, sanırım, yanlış yorum yaparsanız - aşağıdaki durumda, bu dış çift tırnaklardan kaçar:

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

... - o gitzaman (en azından benim için) biraz şifreli mesajla başarısız olur:

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

Bence, gitsadece bir argüman olarak bütün bir dizeyi "gördüğünden" !- yürütülebilir bir dosya olarak çalıştırmaya çalıştı; ve buna karşılık "echo 'A' 'B'"bir dosya olarak bulunamadı .

Her halükarda, git help configyukarıdaki alıntı bağlamında, "git invokation" git new "kabuk komutunu çalıştırmaya eşdeğerdir" gitk --all --not ORIG_HEAD $ @ "; burada $ @, çalışma zamanında komut satırından git komut takma adına iletilen bağımsız değişkenlerdir. ... ". Bunun OP'de "doğrudan" yaklaşımın neden konumsal parametrelerle çalışmadığını da açıklayacağını düşünüyorum.


güzel test. Tüm olasılıkları kontrol etmenin hızlı bir yolu!
albfan

fail"echo 'A' 'B" (yani 10 karakter uzunluğunda) adlı bir komutu çalıştırmaya çalışıyor. Aynı hata sh -c "'echo a b'"ve aynı neden, çok fazla tırnak katmanı
bsb
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.