पोजिशन पैरामीटर के साथ उर्फ ​​जीआईटी


261

मूल रूप से मैं उपनाम की कोशिश कर रहा हूं:

git files 9fa3

... कमांड निष्पादित करने के लिए:

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

लेकिन git, अलियास कमांड में स्थितीय मापदंडों को पास नहीं करता है। मैंने कोशिश की है:

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

... और कुछ अन्य लेकिन काम नहीं किया।

पतित मामला होगा:

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

...मै इसे काम मे कैसे ले सकता हूँ?


17
ध्यान दें कि जीआईटी 1.8.2.1 में ऐसा संभव है कि शेल फ़ंक्शन के बिना (आपके मूल दृष्टिकोण के साथ $1काम करना चाहिए)।
ईमंतस

7
@Eimantas आप एक जवाब में विस्तृत करना चाहते हैं? यह मेरे लिए काम नहीं करता है, और मुझे इसके बारे में कोई दस्तावेज नहीं मिल रहा है।
पावन

@Eimantas हालांकि जारी नोटों में इस बारे में कुछ भी नहीं है ।
Knu

1
मैं पुष्टि कर सकता हूँ कि मैं Git 2.11 में बिना किसी शीनिग के तर्कों के साथ शेल कमांड चला सकता हूँ।
अनारकली

जवाबों:


365

सबसे स्पष्ट तरीका एक शेल फ़ंक्शन का उपयोग करना है:

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

बिना उर्फ ​​के !एक गीट कमांड के रूप में माना जाता है; उदा commit-all = commit -a

इसके साथ !, यह शेल में अपनी स्वयं की कमांड के रूप में चलाया जाता है, जिससे आप इस तरह मजबूत जादू का उपयोग कर सकते हैं।

UPD
क्योंकि आदेशों ${GIT_PREFIX}में फ़ाइल नाम का संदर्भ देते समय आदेशों का उपयोग किया जाता है, जिसे आप रिपॉजिटरी के रूट पर निष्पादित करते हैं


8
धन्यवाद, यह बिलकुल सही लगता है: [alias] files = "! F () {echo $ 3 $ 2 $ 1;}; f"; $ git फाइलें abc => cba
user400575

1
@ KohányiRóbert: यह वास्तव में एक शेल स्क्रिप्ट प्रश्न नहीं है; यह एक विशेष रूप से git config है। बिना उर्फ ​​के !एक गीट कमांड के रूप में माना जाता है; उदा commit-all = commit -a। इसके साथ !, यह शेल में अपनी स्वयं की कमांड के रूप में चलाया जाता है, जिससे आप इस तरह मजबूत जादू का उपयोग कर सकते हैं।
कास्कैबेल

40
सावधान रहें, !रिपॉजिटरी की जड़ पर चलेंगे, इसलिए अपने उपनाम को कॉल करते समय रिश्तेदार रास्तों का उपयोग करने से वे परिणाम नहीं मिलेंगे जो आप उम्मीद कर सकते हैं।
Drealmer

4
@RobertDailey यह इसे तोड़ता नहीं है, यह सिर्फ इसे लागू नहीं करता है। इसे जोड़ने के लिए stackoverflow.com/questions/342969/… देखें ।
कास्कैबेल

3
नोट : यह तर्कों को उद्धृत नहीं करता है (जो सामान्य रूप से खतरनाक है)। साथ ही, एक फ़ंक्शन अनावश्यक है। अधिक स्पष्टीकरण के लिए मेरा जवाब देखें ।
टॉम हेल

96

आप shसीधे संदर्भ भी दे सकते हैं (फ़ंक्शन बनाने के बजाय):

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

(लाइन के अंत में डैश पर ध्यान दें - आपको इसकी आवश्यकता होगी।)


8
यदि आप कमांड साझा कर रहे हैं, तो आप संभवतः इसका उपयोग करना चाहते हैं sh, क्योंकि यह अपने आप में एक शेल है, और यह सिस्टम के विशाल बहुमत पर उपलब्ध है। डिफ़ॉल्ट शेल का उपयोग केवल तभी काम करता है जब कमांड सभी शेल के लिए लिखे गए अनुसार काम करता है।
नोमोटेटिस

12
मैं पसंद --करता हूं -क्योंकि यह कुछ हद तक गलती से स्टिंग के लिए अधिक परिचित और कम संभावना है। ("एक तर्क - के बराबर है -" बैश में (1) अप्राप्य है)
bsb


5
अंत '-' का सही अर्थ क्या है और यह कहाँ प्रलेखित है?
Zitrax

5
नोट : यह तर्कों को उद्धृत नहीं करता है (जो सामान्य रूप से खतरनाक है)। उप-शेल (के साथ sh -c) बनाना भी अनावश्यक है। एक विकल्प के लिए मेरा जवाब देखें ।
टॉम हेल

81

आप जिस उपनाम की तलाश कर रहे हैं, वह है:

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

तर्क सत्यापन के साथ:

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

अंतिम# महत्वपूर्ण है - यह खोल (यह उन्हें टिप्पणी बाहर) द्वारा कार्रवाई की जा रही से सभी उपयोगकर्ता के आपूर्ति की बहस से बचाता है।

नोट: gitकमांड लाइन के अंत में सभी उपयोगकर्ता द्वारा दिए गए तर्क देते हैं। इस क्रिया को देखने के लिए, प्रयास करें:GIT_TRACE=2 git files a b c d

बच गए (घोंसले के शिकार के कारण) रिक्त स्थान के लिए फ़ाइलनाम के लिए उद्धरण महत्वपूर्ण हैं या "; rm -rf --no-preserve-root /;)


सबसे सरल मामलों के लिए यह सही उत्तर है, वास्तव में इसे किसी फ़ंक्शन या श-सी में लपेटकर जटिल करने की आवश्यकता नहीं है।
एड रान्डेल

4
हां, !पहले से ही पता चलता है sh -c(दिखावा करते समय GIT_TRACE=2), इसलिए एक और उप-शेल चलाने की आवश्यकता नहीं है। अधिक जटिल मामलों में आप क्या मुद्दे देखते हैं?
टॉम हेल

यदि आप डिफ़ॉल्ट तर्क सेट करना चाहते हैं तो क्या यह काम करता है? उदाहरण के लिए मैं एक Github PR लाने के लिए ऐसा करना चाहता हूं fp = "! 1=${1:-$(git headBranch)}; 2=${2:-up}; git fetch -fu $2 pull/$1/head:$1; git checkout $1; git branch -u $2 #":। यह पहले दो बयानों के बिना बहुत अच्छा काम करता है, लेकिन अगर आप उनका उपयोग करते हैं तो गिर जाते हैं। (मेरे पास headBranch = symbolic-ref --short HEADभी है)।
गिब

2
यह काम किया है, यह काम करता है अगर आप नए params सेट, तो यह ठीक है fp = "! a=${1:-$(git headBranch)}; b=${2:-up}; git fetch -fu $b pull/$a/head:$a; git checkout $a; git branch -u $b #":।
गिब

"उद्धरण की आवश्यकता क्यों है ?
यूजेन कोनकोव

27

उपनाम प्रसंस्करण को पारदर्शी बनाने के लिए git मैन पेज पर वर्णित GIT_TRACE = 1 का उपयोग करें:

$ 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

आपके मूल कमांड git संस्करण 1.8.3.4 के साथ काम करते हैं (Eimantas ने नोट किया कि यह 1.8.2.1 में बदल गया है)।

sh -c '..' --और f() {..}; fविकल्प दोनों सफाई से संभाल "$ @" अलग अलग तरीकों से मानकों (GIT_TRACE साथ देखें)। उपनाम के लिए "#" को लागू करना भी अनुगामी मापदंडों को अनुगामी छोड़ने के बिना अनुमति देगा।


1
स्पष्टीकरण के लिए धन्यवाद: वे आदेश आपकी समस्या के बाद मूल समस्या पर मेरे लिए काम करते हैं:files = "!git diff --name-status $1^ $1 #" files = "!git diff --name-status $1^"
user2291758

20

जैसा कि ऊपर Drealmer द्वारा कहा गया है :

" सावधान रहे, ! रिपॉजिटरी के मूल में चलेगा, इसलिए अपने उपनाम को कॉल करते समय रिश्तेदार रास्तों का उपयोग करने से वे परिणाम नहीं मिलेंगे जो आप उम्मीद कर सकते हैं। - Drealmer अगस्त 8 '13 16:28 »

GIT_PREFIX आपके द्वारा जिस उपनिर्देशिका में git द्वारा सेट किया जा रहा है, आप पहले निर्देशिका को बदलकर इसे दरकिनार कर सकते हैं:

git config --global alias.ls '! सीडी "$ {GIT_PREFIX: -।}"; ls -al '


मुझे इससे भी परेशानी हो रही है (रिपॉजिटरी के मूल में कमांड चलाए जा रहे हैं) लेकिन यह समाधान कुछ भी नहीं करता है। (अगर यह मायने रखता है, तो मैं ओएस एक्स का उपयोग कर रहा हूं)
वाल्ड्रिअस

उफ़ ... गिट उर्फ ​​एक उपनाम है जिसे मैंने बनाया है।
पियरे-ओलिवियर वेर्स

(git 1.8.2 के बाद से) git config --set alias.alias = '! git config --global alias। $ 1 "$ 2" '
पियरे-ओलिवियर वेर्स

यह मेरे लिए काम करना समाप्त हो गया है: "अपने git उपनामों को उपसर्ग करें (जो शेल कमांड चलाते हैं और सही pwd की आवश्यकता होती है) cd ${GIT_PREFIX:-.} &&." (स्रोत: stackoverflow.com/a/21929373/266309 )
वाल्ड्रि

यह बोली करो। !cd "${GIT_PREFIX:-.}" && ls -al
मिराबिलोस

8

मैं एक उपनाम के साथ ऐसा करना चाहता था जो यह करता है:

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

अंत में, मैंने 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 $1;
git merge --ff-only $2;
git branch -d $2;

यह लाभ यह है कि यह है बहुत क्योंकि यह एकाधिक पंक्तियों में और अधिक सुपाठ्य। इसके अलावा मुझे बैश कॉल करने में सक्षम होना पसंद है -xऔर set -e। आप शायद इस पूरे काम को एक उपनाम के रूप में कर सकते हैं, लेकिन यह सुपर बदसूरत और बनाए रखना मुश्किल होगा।

क्योंकि फ़ाइल नाम है git-mआप इसे इस तरह से चला सकते हैं:git m foo bar


1
मुझे यह बहुत अधिक पसंद है, लेकिन मुझे यह पता नहीं चल पाया है कि मैं इस दृष्टिकोण के साथ ऑटोकॉम्पट का उपयोग कैसे कर सकता हूं। उपनाम पर आप ऐसा कर सकते हैं: '!f() { : git branch ; ... }; f'और यह एक शाखा के रूप में उपनाम को स्वत: पूर्ण कर देगा जो सुपर काम है।
हस्सेक

हाँ, मुझे लगता है कि मैं पथ पर व्यक्तिगत स्क्रिप्ट फ़ाइलों के रूप में गैर-तुच्छ चीजों को करना पसंद करता हूं। नीचे की ओर हालांकि हां है, आप संदर्भ जैसी चीजों को स्वचालित रूप से पूरा करते हैं। हालाँकि आप इसे स्वयं अपने ऑटो-पूर्ण को कॉन्फ़िगर करके ठीक कर सकते हैं। हालांकि, मुझे यह पसंद है कि आप किसी स्क्रिप्ट को पथ पर एक फ़ोल्डर में छोड़ सकते हैं और यह काम करना शुरू कर देगा, लेकिन ऑटो-पूर्ण होने के लिए, आपको इसे 'लोड' करने की आवश्यकता है, इसलिए आमतौर पर यह मेरी .bashrcफ़ाइल में है कि मैं स्रोत हूं। लेकिन मुझे नहीं लगता कि मैं एक स्क्रिप्ट में ऑटो-आर्ग्युमेंट को उतनी ही बदल देता हूं जितना कि स्क्रिप्ट में ही होता है, और यह केवल देव के दौरान होगा।
Thecoshman

4

बस कुछ इसी तरह से टकराया; आशा है कि यह मेरे नोट्स पोस्ट करने के लिए ओ.के. एक बात जो मुझे gitतर्क के साथ उपनामों के बारे में भ्रमित करती है, शायद git help configउससे आती है (मेरे पास git संस्करण 1.7.9.5 है):

यदि उर्फ ​​विस्तार को विस्मयादिबोधक बिंदु के साथ उपसर्ग किया जाता है, तो इसे शेल कमांड के रूप में माना जाएगा। उदाहरण के लिए, "alias.new =! Gitk --all --not ORIG_HEAD" को परिभाषित करना, मंगलाचरण "git new" शेल कमांड "gitk --all-not 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[[\"$0\"]] 1-\"$1\"/ A-"$@"/ "
  fechargs = "! f() { echo 0[[\"$0\"]] 1-\"$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[["$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/

... या: जब आप !किसी gitअन्य में "जैसा है" के बाद "सादे" कमांड का उपयोग कर रहे हैं - तो gitस्वचालित रूप से उस कमांड में तर्क सूची को जोड़ देता है! इससे बचने का एक तरीका, वास्तव में, आपकी स्क्रिप्ट को एक फ़ंक्शन के रूप में - या तर्क के रूप में कॉल करना है sh -c

यहां (मेरे लिए) एक और दिलचस्प बात यह है कि एक शेल स्क्रिप्ट में, एक व्यक्ति आमतौर पर स्क्रिप्ट $0के फ़ाइल नाम के लिए स्वचालित चर की अपेक्षा करता है । लेकिन एक gitउपनाम फ़ंक्शन के लिए, $0तर्क मूल रूप से, पूरे स्ट्रिंग की सामग्री उस कमांड को निर्दिष्ट करता है (जैसा कि कॉन्फ़िगरेशन फ़ाइल में दर्ज किया गया है)।

यही कारण है कि, मुझे लगता है, अगर आप गलत तरीके से होते हैं - नीचे के मामले में, जो बाहरी दोहरे उद्धरणों से बच जाएगा:

[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 कमांड उपनाम के लिए दिए गए तर्क हैं ... "। मुझे लगता है कि यह भी समझाएगा, क्यों ओपी में "प्रत्यक्ष" दृष्टिकोण स्थितीय मापदंडों के साथ काम नहीं करता है।


अच्छा परीक्षण। सभी संभावनाओं की जांच करने का एक त्वरित तरीका!
एल्बफैन

fail"echo 'A' B" नामक एक कमांड चलाने की कोशिश कर रहा है (यानी। 10 वर्ण लंबा)। उसी त्रुटि से sh -c "'echo a b'"और उसी कारण से, उद्धरणों की बहुत सी परतें
bsb
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.