Git में, मैं एक ही प्रतिबद्ध में एक फ़ाइल में वर्तमान प्रतिबद्ध हैश कैसे लिख सकता हूं


131

मैं एक फैंसी सामान करने की कोशिश कर रहा हूँ यहाँ Git हुक के साथ, लेकिन मैं वास्तव में नहीं जानता कि यह कैसे करना है (या यदि यह संभव है)।

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

कोई विचार?


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

29
यह एक बहुत ही व्यावहारिक समस्या है। मैं उसमें भी भागा!
ली डोंग

7
मेरे लिए, मैं अपने कार्यक्रम को लॉग्स को एक संदेश लिखना पसंद करूंगा: "myprog start up, v.56c6bb2"। इस तरह, अगर कोई बग दर्ज करता है और मुझे लॉग फाइल भेजता है, तो मुझे पता चल सकता है कि मेरे प्रोग्राम का कौन सा संस्करण चल रहा था।
एडवर्ड फॉक

5
@ जेफ्रोमी, वास्तविक उपयोग का मामला वास्तव में बहुत आम है, और शुरुआती लोगों को बहुत आसानी से हिट करता है। असली संस्करण को किसी भी तरह से "सही" फ़ाइल को आधारभूत फाइलों में रखना एक बुनियादी जरूरत है, और यह स्पष्ट रूप से दूर है कि यह एक गलत विचार क्यों होगा, उदाहरण के लिए, क्योंकि मैन्युअल संशोधन नियंत्रण हैक्स के साथ यह आपका एकमात्र विकल्प है। (शुरुआती याद रखें।) यह जोड़ें कि कई परियोजनाओं में बस किसी भी प्रकार का निर्माण / स्थापना / तैनाती कदम नहीं है जो कि संस्करण को लाइव फ़ाइलों में ले जा सकता है और मुहर लगा सकता है। भले ही, पूर्व-प्रतिबद्ध के बजाय, पोस्ट-चेकआउट हुक उन मामलों में भी मदद कर सकता है।
एस.जे.

यह असंभव है! यदि आप ऐसा कर सकते हैं तो आपने SHA-1 हैश एल्गोरिथ्म को तोड़ दिया ... ericsink.com/vcbe/html/cryptographic_haffes.html
betontalpfa

जवाबों:


82

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

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


3
किसी और को यह कैसे करना है पर कदम से एक कदम के साथ आगे निकल सकता है? या कम से कम सही दिशा में एक कुहनी से हलका धक्का?
जोएल वॉर्शम

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

1
मेरे मामले में, मैंने अपने मेकफाइल में एक नियम जोड़ा है जो हर बिल्ड पर "gitversion.h" फाइल बनाता है। देखें stackoverflow.com/a/38087913/338479
एडवर्ड फॉक

1
आप इसे "गिट-चेकआउट" हुक के साथ स्वचालित करने में सक्षम हो सकते हैं। समस्या यह है कि हुक को मैन्युअल रूप से स्थापित करना होगा।
एडवर्ड फॉक

14

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

हालाँकि, तीन विकल्प हैं:

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

मैं एक हुक स्क्रिप्ट पर काम कर रहा हूं, इसे 'यहां तब करूंगा जब यह पूरा हो जाएगा', लेकिन फिर भी - इससे पहले ड्यूक नुकेम फॉरएवर जारी किया गया था:)

अद्यतन : के लिए कोड.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 जोड़े को एक वास्तविक प्रतिबद्ध हैश में :)

मुझे नहीं पता कि यह तरीका बता सकता है कि विलय विलय अलग हो सकता है। जल्द ही इसकी जांच कराएंगे


13

किसी ने मुझे पहचान पर "आदमी gitattributes" खंड की ओर इशारा किया, जिसमें यह है:

अध्यक्ष

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

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


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

11

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

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


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

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

@o_O ट्यूनिक: संभव नहीं। परिवर्तित फ़ाइल का मतलब हैश (एक फ़ाइल का) बदल गया है - यह डिज़ाइन द्वारा, और हैश फ़ंक्शन की परिभाषा से है।
जकुब नारबस्की

2
यह एक बहुत अच्छा समाधान है, लेकिन ध्यान रखें कि इसमें हुक शामिल होते हैं जिन्हें मैन्युअल रूप से स्थापित करना होता है जब भी आप एक रिपॉजिटरी को क्लोन करते हैं।
एडवर्ड फॉक

7

कमिट बॉक्स के बाहर सोचो!

इसे फ़ाइल हुक / पोस्ट-चेकआउट में पॉप करें

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

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


3

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


1

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

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

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

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

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

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


क्या कोई ऐसा तरीका है जिससे कोई फाइल कर सकता है, फिर एक चेकआउट करें और नवीनतम कमिट हैश को प्रत्येक स्रोत कोड फ़ाइल की शुरुआत में एक टिप्पणी के रूप में रखा जाए? फिर उस से निर्माण और भाग?
जॉन वूटेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.