2010-08-09 10 views
84

मैं गिट हुक के साथ यहां एक फैंसी सामान करने की कोशिश कर रहा हूं, लेकिन मुझे वास्तव में यह नहीं पता कि यह कैसे करना है (या यदि यह है मुमकिन)।गिट में, मैं वर्तमान प्रतिबद्ध हैश को उसी प्रतिबद्धता में एक फ़ाइल में कैसे लिख सकता हूं

मुझे क्या करना है: प्रत्येक प्रतिबद्धता में मैं अपने हैश लेना चाहता हूं और फिर इस हैश के साथ प्रतिबद्धता में एक फ़ाइल अपडेट करना चाहता हूं।

कोई विचार?

+0

यहां आपका वास्तविक अंत लक्ष्य क्या है? यह ऐसा कुछ है जिसे आप वास्तव में करना चाहते हैं, और मिडटीबी कहते हैं, यह अनिवार्य रूप से असंभव है। – Cascabel

+9

असल में मेरे पास एक वेब एप्लिकेशन है और मैं उस एप्लिकेशन के एक स्थापित संस्करण को उस सटीक प्रतिबद्धता के साथ जोड़ना चाहता हूं जो संस्करण से जुड़ा हुआ है। मेरी प्रारंभिक विचारधारा प्रतिबद्ध हैश के साथ about.html फ़ाइल को अपडेट करना था। लेकिन गिट के ऑब्जेक्ट मॉडल का अध्ययन करने के बाद, मुझे एहसास हुआ कि यह असंभव है =/ –

+13

यह एक बहुत ही व्यावहारिक समस्या है। मैं भी इसमें भाग गया! –

उत्तर

59

मैं आपके मन में जो कुछ भी रखता हूं उसके समान कुछ करने की अनुशंसा करता हूं: SHA1 को अनट्रैक फ़ाइल में रखकर, बिल्ड/स्थापना/तैनाती प्रक्रिया के हिस्से के रूप में उत्पन्न किया गया है। यह स्पष्ट रूप से करना आसान है (git rev-parse HEAD > filename या शायद git describe [--tags] > filename), और यह किसी फ़ाइल के साथ समाप्त होने की तरह पागल कुछ भी करने से बचाता है जो कि गिट की ट्रैकिंग से अलग है।

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

+2

अच्छा बिंदु। यह एक क्लीनर समाधान है। धन्यवाद। –

+1

क्या कोई इसे आगे बढ़ाने के चरणबद्ध तरीके से आगे बढ़ सकता है? या कम से कम सही दिशा में एक झुकाव? –

+1

@ जोएल कैसे करें? मैंने बताया कि हैश को फाइल में कैसे रखा जाए; बाकी संभवतः आपकी निर्माण प्रक्रिया के बारे में कुछ है? शायद आप एक नया सवाल अगर आप उस हिस्से के बारे में पूछने की कोशिश कर रहे हैं। – Cascabel

8

gitattributes में filter विशेषता का उपयोग कर इसे प्राप्त किया जा सकता है। आपको smudge कमांड प्रदान करना होगा जो प्रतिबद्ध आईडी को सम्मिलित करता है, और clean कमांड जो इसे हटा देता है, जैसे कि इसमें डाली गई फ़ाइल केवल प्रतिबद्ध आईडी के कारण नहीं बदलेगी।

इस प्रकार, प्रतिबद्ध आईडी फ़ाइल के ब्लॉब में कभी संग्रहित नहीं होती है; यह सिर्फ आपकी कामकाजी प्रति में विस्तारित है। (वास्तव में ब्लॉब में प्रतिबद्ध आईडी डालने से असीम पुनरावर्ती कार्य बन जाएगा। ☺) जो भी इस पेड़ को क्लोन करता है उसे अपने लिए विशेषताओं को स्थापित करने की आवश्यकता होगी।

+1

हमम जो वादा करता है! बहुत बहुत धन्यवाद! मैं यहाँ कुछ सामान आज़माउंगा! –

+7

** असंभव ** कार्य, रिकर्सिव कार्य नहीं। Commit हैश पेड़ हैश पर निर्भर करता है जो फ़ाइल हैश पर निर्भर करता है, जो फ़ाइल सामग्री पर निर्भर करता है। आपको आत्म-स्थिरता प्राप्त करनी है। जब तक आपको SHA-1 हैश के लिए * [सामान्यीकृत] निश्चित बिंदु * नहीं मिलेगा। –

+1

@ जकूब, क्या गिट में कुछ प्रकार की चाल है जो ट्रैक की गई फाइलें बनाने की अनुमति देगी जो परिणामस्वरूप हैश को संशोधित नहीं करती हैं? शायद अपने हैश को ओवरराइड करने का कोई तरीका। यह एक समाधान होगा :) – kolypto

2

मुझे नहीं लगता कि आप वास्तव में ऐसा करना चाहते हैं, क्योंकि जब प्रतिबद्धता में एक फ़ाइल बदल जाती है, तो प्रतिबद्धता का हैश भी बदल जाता है।

10

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

  1. बढ़ाने के लिए कहीं न कहीं 'आईडी प्रतिबद्ध' और शामिल यह एक स्क्रिप्ट का उपयोग करें:

    हालांकि, वहाँ तीन विकल्प हैं। बदसूरत

  2. । उस फ़ाइल को संपादित करें जिसे आप हैश को स्टोर करने जा रहे हैं। बहुत आसान नहीं
  3. pre-commit में, पिछले प्रतिबद्ध हैश स्टोर करें :) आप 99.99% मामलों में बदलाव/सम्मिलित नहीं करते हैं, इसलिए, यह काम करेगा। सबसे बुरे मामले में आप अभी भी स्रोत संशोधन की पहचान कर सकते हैं।

मैं एक हुक स्क्रिप्ट पर काम कर रहा हूँ, इसे यहाँ पोस्ट करेंगे 'इसके पूर्ण होने पर', लेकिन अभी भी - ड्यूक Nukem हमेशा जारी किया गया है :)) से पहले

युपीडी: .git/hooks/pre-commit के लिए कोड:

#!/usr/bin/env bash 
set -e 

#=== 'prev-commit' solution by o_O Tync 
#commit_hash=$(git rev-parse --verify HEAD) 
commit=$(git log -1 --pretty="%H%n%ci") # hash \n date 
commit_hash=$(echo "$commit" | head -1) 
commit_date=$(echo "$commit" | head -2 | tail -1) # 2010-12-28 05:16:23 +0300 

branch_name=$(git symbolic-ref -q HEAD) # http://stackoverflow.com/questions/1593051/#1593487 
branch_name=${branch_name##refs/heads/} 
branch_name=${branch_name:-HEAD} # 'HEAD' indicates detached HEAD situation 

# Write it 
echo -e "prev_commit='$commit_hash'\ndate='$commit_date'\nbranch='$branch'\n" > gitcommit.py 

अब केवल एक ही चीज़ हम की जरूरत है एक उपकरण है कि एक असली के लिए prev_commit,branch जोड़ी धर्मान्तरित हैश :)

प्रतिबद्ध रहा है कि क्या वें पता नहीं है है दृष्टिकोण विलय बता सकता है अलग करता है।यह जाँच से बाहर होगा जल्द ही

12

किसी ने बताया मुझे "आदमी gitattributes" के अध्यक्ष पर खंड है, जो इस है:

अध्यक्ष

विशेषता अध्यक्ष एक पथ के लिए सेट किया जाता है, Git की जगह $ ईद $ आईडी के साथ ब्लॉब ऑब्जेक्ट में $ :, 40-वर्ण हेक्साडेसिमल ब्लॉब ऑब्जेक्ट नाम के बाद, चेकआउट पर डॉलर के हस्ताक्षर $ के बाद। कोई भी बाइट अनुक्रम जो $ आईडी के साथ शुरू होता है: और वर्कट्री फ़ाइल में $ के साथ समाप्त होता है चेक-इन पर $ आईडी $ के साथ बदल दिया जाता है।

यदि आप इसके बारे में सोचते हैं, तो यही सीवीएस, सबवर्जन आदि भी करता है। यदि आप रिपॉजिटरी को देखते हैं, तो आप देखेंगे कि रिपॉजिटरी में फ़ाइल हमेशा शामिल है, उदाहरण के लिए, $ आईडी $। इसमें इसका विस्तार कभी नहीं होता है। यह केवल चेकआउट पर है कि पाठ का विस्तार किया गया है।

+6

'पहचान' फ़ाइल के लिए हैश है, प्रतिबद्धता की शुरुआत नहीं। Http://git-scm.com/book/en/Customizing-Git-Git-Attributes#Keyword- एक्सटेंशन: "हालांकि, इसका परिणाम सीमित उपयोग है। यदि आपने सीवीएस या सबवर्जन में कीवर्ड प्रतिस्थापन का उपयोग किया है, तो आप एक डेटास्टैम्प शामिल कर सकते हैं - एसएचए सभी सहायक नहीं है, क्योंकि यह काफी यादृच्छिक है और आप यह नहीं बता सकते कि एक एसएचए बड़ा है या दूसरे से नया है। " 'फ़िल्टर' काम करता है, लेकिन यह एक फ़ाइल में (और बाहर) की प्रतिबद्ध जानकारी प्राप्त कर सकता है। –

0

मुझे यह पता लगाने दें कि यह गिट आंतरिक का उपयोग करके एक चुनौतीपूर्ण समस्या क्यों है। आप

#!/bin/bash 
commit=$(git cat-file commit HEAD) # 
sha1=($((printf "commit %s\0" $(echo "$commit" | wc -c); echo "$commit") | sha1sum)) 
echo ${sha1[0]} 

अनिवार्य रूप से आप संदेश git cat-file commit HEAD द्वारा दिया पर एक SHA1 चेकसम चलाने से वर्तमान की SHA1 प्रतिबद्ध मिल सकती है। जब आप इस संदेश की जांच करते हैं तो दो चीजें तुरंत एक समस्या के रूप में बाहर निकलती हैं। एक पेड़ sha1 है और दूसरा प्रतिबद्ध समय है।

अब प्रतिबद्ध समय आसानी से संदेश को बदलकर और अनुमान लगाया जाता है कि किसी विशिष्ट समय पर प्रतिबद्ध करने या शेड्यूल करने में कितना समय लगता है। सही मुद्दा पेड़ sha1 है, जिसे आप git ls-tree $(git write-tree) | git mktree से प्राप्त कर सकते हैं। अनिवार्य रूप से आप ls-tree से संदेश पर sha1 चेकसम कर रहे हैं, जो सभी फ़ाइलों और उनके sha1 चेकसम की एक सूची है।

इसलिए आपकी प्रतिबद्धता sha1 चेकसम आपके पेड़ sha1 चेकसम पर निर्भर करती है, जो सीधे फाइल sha1 चेकसम पर निर्भर करती है, जो सर्कल को पूरा करती है और प्रतिबद्ध sha1 पर निर्भर करती है। इस प्रकार आपके पास उपलब्ध तकनीकों के साथ एक परिपत्र समस्या है।

less secure checksums के साथ, फाइल को फ़ाइल में चेकसम को ब्रूट फोर्स के माध्यम से लिखना संभव दिखाया गया है; हालांकि, मुझे किसी भी काम के बारे में पता नहीं है जिसने sha1 के साथ उस कार्य को पूरा किया। यह असंभव नहीं है, लेकिन हमारी वर्तमान समझ के साथ असंभव के बगल में (लेकिन जो कुछ वर्षों में शायद जानता है यह छोटा होगा)। हालांकि, अभी भी बलपूर्वक बल के लिए यह कठिन है क्योंकि आपको फाइल में एक (ब्लॉब) चेकसम के (पेड़) चेकसम के (प्रतिबद्ध) चेकसम लिखना है।

0

प्रतिबद्ध बॉक्स के बाहर सोचें!

फ़ाइल हुक/उत्तर चेकआउट

#!/bin/sh 
git describe --all --long > config/git-commit-version.txt 

संस्करण में पॉप इस हर जगह आप इसका इस्तेमाल उपलब्ध हो जाएगा।

संबंधित मुद्दे

 संबंधित मुद्दे