2012-09-07 14 views
13

में किए जाने वाले कार्यों का परीक्षण करना इंटरनेट इस प्रश्न के गलत और गैर-आदर्श उत्तरों से पूरी तरह से परेशान है। यह दुर्भाग्यपूर्ण है क्योंकि आपको लगता है कि यह एक आम बात होगी जो आप करना चाहते हैं।प्री-प्रतिबद्ध हुक

समस्या: जब pre-commit हुक चलाता है, तो भंडार साफ नहीं हो सकता है। इसलिए यदि आप अपने परीक्षणों को नैतिक रूप से चलाते हैं, तो वे आपके द्वारा किए जा रहे कार्यों के खिलाफ नहीं होंगे, लेकिन आपके काम करने वाले पेड़ में जो भी गंदगी होती है।

करने के लिए स्पष्ट बात pre-commit और git pop निकास पर के शुरू में git stash --keep-index --include-untracked है। इस तरह आप (शुद्ध) इंडेक्स के खिलाफ परीक्षण कर रहे हैं, जो हम चाहते हैं।

दुर्भाग्य से, इस संघर्ष मार्करों विलय अगर आप git add --patch उपयोग करते हैं, (विशेष रूप से आप जिसे संपादित करते हैं), के बाद से [email protected]{0} की सामग्री काम पेड़ के खिलाफ मेल नहीं खा सकते बाद प्रतिबद्ध उत्पन्न करता है।

एक और आम समाधान भंडार को क्लोन करना और परीक्षण को एक नए अस्थायी में चलाने के लिए है। इसके साथ दो मुद्दे हैं: एक यह है कि हमने अभी तक प्रतिबद्ध नहीं किया है, इसलिए हम उस राज्य में रिपोजिटरी की एक प्रति आसानी से प्राप्त नहीं कर सकते हैं, जिसे हम प्रतिबद्ध करने वाले हैं (मुझे यकीन है कि ऐसा करने का एक तरीका है , लेकिन मुझे दिलचस्पी नहीं है क्योंकि :)। दूसरा, मेरे परीक्षण वर्तमान कार्यशील निर्देशिका के स्थान के प्रति संवेदनशील हो सकते हैं। उदाहरण के लिए स्थानीय पर्यावरण विन्यास की वजह से।

तो: मैं अपने कार्य-पेड़ को git stash --keep-index --include-untracked से पहले जो भी स्थिति में विलय विवाद मार्कर शुरू किए बिना, और पोस्ट-प्रतिबद्ध HEAD को संशोधित किए बिना कैसे कर सकता हूं?

+0

स्क्रिप्ट पूर्व प्रतिबद्ध डेटा प्राप्त इनपुट के रूप में प्रतिबद्ध जा रहा है। आपको किसी और चीज को देखने की ज़रूरत क्यों है? शायद आप जो करने की कोशिश कर रहे हैं वह पूर्व-प्रतिबद्ध हुक के अलावा किसी अन्य चीज़ में किया जाएगा। आप किस तरह के परीक्षण करना चाहते हैं जिसके लिए पूर्ण भंडार तक पहुंच की आवश्यकता है? –

+0

@ विलियमपर्सेल: "डेटा प्रतिबद्ध होने" से आपका क्या मतलब है? प्री-स्क्रिप्ट स्क्रिप्ट मेरे काम के पेड़ में चलती है (यानी, स्रोत भंडार का आधार)। समस्या यह है कि यदि आप भंडार में कुछ बदलाव करते हैं और केवल उनमें से कुछ को चरणबद्ध करते हैं (उदाहरण के लिए, आप कुछ फाइलें जोड़ते हैं लेकिन दूसरों को नहीं), तो आप ऐसा होने से पहले प्रतिबद्धता का परीक्षण नहीं करेंगे (मैं क्या करना चाहता हूं) आप अपनी कार्यशील निर्देशिका में जो भी हो, उसका परीक्षण करेंगे। – pwaller

+0

जो पैच आप कर रहे हैं वह पूर्व-प्रतिबद्ध हुक में stdin पर उपलब्ध है। यदि पैच किया जा रहा है तो क्या आप परीक्षण कर रहे हैं? पूर्व-प्रतिबद्ध हुक का उद्देश्य पैच को सत्यापित करना है। –

उत्तर

2

यदि संपूर्ण रेपो क्लोनिंग बहुत महंगा है, तो शायद आपको केवल कार्यशील निर्देशिका की एक प्रति की आवश्यकता है। एक प्रतिलिपि बनाना संघर्ष से निपटने की कोशिश करने से आसान होगा। उदाहरण के लिए:

#!/bin/sh -e 

trap 'rm -rf $TMPD' 0 
mkdir ${TMPD=$PWD/.tmpdir} 
git ls-tree -r HEAD | while read mod type sha name; do 
    if test "$type" = blob; then 
     mkdir -p $TMPD/$(dirname "$name") 
     git show $sha > $TMPD/"$name"; 
     chmod $mod $TMPD/"$name" 
    fi 
done 
cd $TMPD 
git diff --cached HEAD | patch 
# Run tests here 

इस पेड़ के राज्य डंप हो जाएगा के रूप में यह $ TMPD में प्रतिबद्ध के बाद हो जाएगा, तो आप अपने परीक्षण वहाँ चला सकते हैं। आपको यहां से अधिक सुरक्षित फैशन में एक अस्थायी निर्देशिका मिलनी चाहिए, लेकिन अंतिम अंतर को काम करने के लिए (या पहले स्क्रिप्ट और सीडी को सरल बनाने के लिए), यह कार्यशील निर्देशिका का बच्चा होना चाहिए।

-1

मुझे अंत में समाधान मिला है जिसे मैं ढूंढ रहा था। प्रतिबद्ध होने से पहले केवल सूचकांक की स्थिति की जांच की जाती है, और यह इंडेक्स और काम करने वाले पेड़ को ठीक उसी तरह छोड़ देता है जैसा कि प्रतिबद्धता से पहले था।

यदि आपको कोई समस्या या बेहतर तरीका दिखाई देता है, तो कृपया एक टिप्पणी या अपना उत्तर के रूप में उत्तर दें।

यह मानता है कि कुछ और भी गिट रिपोजिटरी या काम करने वाले पेड़ को चलाने के दौरान इसे चलाने या अन्यथा संशोधित करने का प्रयास नहीं करेगा। यह कोई वारंटी के साथ आता है, गलत हो सकता है और हवा में अपना कोड फेंक सकता है। सावधानी से प्रयोग करें।

# pre-commit.sh 
REPO_PATH=$PWD 
git stash save -q --keep-index --include-untracked # ([email protected]{1}) 
git stash save -q         # ([email protected]{0}) 

# Our state at this point: 
# * clean worktree 
# * [email protected]{0} contains what is to be committed 
# * [email protected]{1} contains everything, including dirt 

# Now reintroduce the changes to be committed so that they can be tested 
git stash apply [email protected]{0} -q 

git_unstash() { 
    G="git --work-tree \"$REPO_PATH\" --git-dir \"$REPO_PATH/.git\"" 
    eval "$G" reset -q --hard    # Clean worktree again 
    eval "$G" stash pop -q [email protected]{1}  # Put worktree to original dirty state 
    eval "$G" reset -q [email protected]{0} .  # Restore index, ready for commit 
    eval "$G" stash drop -q [email protected]{0}  # Clean up final remaining stash 
} 
trap git_unstash EXIT 

... tests against what is being committed go here ... 
+0

जैसा कि निम्नलिखित पोस्ट में टिप्पणियों में उल्लिखित है, यह प्रतिबद्धता में संशोधन करते समय सही तरीके से काम नहीं करेगा, या यदि आपके पास गंदे काम करने वाले पेड़ नहीं हैं। http: // codeinthehole।com/writing/tips-for-use-a-git-pre-commit-hook/ – pwaller

2

आप एक अस्थायी निर्देशिका का उपयोग करने के लिए खर्च कर सकते हैं (। यानी वर्तमान चेकआउट का एक पूरा प्रतिलिपि बनाने) तुम इतनी तरह एक अस्थायी निर्देशिका का उपयोग कर सकते हैं:

tmpdir=$(mktemp -d) # Or put it wherever you like 
git archive HEAD | tar -xf - -C "$tmpdir" 
git diff --staged | patch -p1 -d "$tmpdir" 
cd "$tmpdir" 
... 

यह मूलतः विलियम Pursell की है समाधान लेकिन git archive का लाभ लेता है जो कोड को सरल बनाता है, और मुझे उम्मीद है कि यह तेज़ होगा।

वैकल्पिक रूप से, पहले cd'ing द्वारा:

cd somewhere 
git -C path/to/repo archive HEAD | tar -xf - 
git -C path/to/repo diff --staged | patch -p1 
... 

git -C Git 1.8.5 की आवश्यकता है।

+0

मैंने आपको वोट दिया है, लेकिन यह "परीक्षण करते समय $ PWD में रहने" को संतुष्ट नहीं करता है, जो कुछ सिस्टम के लिए आवश्यक है, जैसे पुस्तकालय जाओ। – pwaller

+0

पावेलर की चिंताओं के अलावा, मेरा मानना ​​है कि यह समाधान काम नहीं करता है अगर आप 'गिट प्रतिबद्ध-ए' कर रहे हैं, क्योंकि आपकी स्क्रिप्ट मानती है कि हम केवल चरणबद्ध फाइलें कर रहे हैं। – TanguyP

1

git write-treepre-commit हुक में उपयोगी है। यह इंडेक्स के रेपो में एक पेड़ लिखता है (इस पेड़ का पुन: उपयोग किया जाएगा जब प्रतिबद्धता को अंतिम रूप दिया जाएगा।)

एक बार पेड़ रेपो को लिखा जाता है, तो आप पेड़ को अस्थायी निर्देशिका में लिखने के लिए git archive | tar -x का उपयोग कर सकते हैं ।

उदा .:

#!/bin/bash 

TMPDIR=$(mktemp -d) 
TREE=$(git write-tree) 
git archive $TREE | tar -x -C $TMPDIR 

# Run tests in $TMPDIR 

RESULT=$? 
rm -rf "$TMPDIR" 
exit $RESULT 
संबंधित मुद्दे