क्या गिट का अर्ध-गुप्त खाली पेड़ वस्तु विश्वसनीय है, और इसके लिए एक प्रतीकात्मक नाम क्यों नहीं है?


125

गिट में एक प्रसिद्ध, या कम से कम सॉर्ट-ऑफ-जानी-पहचाना, खाली पेड़ है जिसका SHA1 है:

4b825dc642cb6eb9a060e54bf8d69288fbee4904

(आप इसे किसी भी रेपो में देख सकते हैं, यहां तक ​​कि एक नया बनाया गया, जिसके साथ git cat-file -tऔर git cat-file -p)।

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

यह एक तर्क के रूप में अधिक उपयोगी है git diff-tree, जो नमूना हुक में से एक करता है।

मैं जो सोच रहा हूं वह है,

  1. यह कितना विश्वसनीय है - यानी, भविष्य के कुछ संस्करण में गिट ऑब्जेक्ट गिने नहीं होंगे 4b825dc642cb6eb9a060e54bf8d69288fbee4904?
  2. खाली पेड़ के लिए कोई प्रतीकात्मक नाम क्यों नहीं है (या वहाँ एक है?)।

(प्रतीकात्मक नाम बनाने के लिए एक त्वरित और गंदा तरीका SHA1 को अंदर रखना है, उदाहरण के लिए .git/Nulltree। दुर्भाग्य से आपको हर रेपो के लिए ऐसा करना होगा। सिर्फ मैजिक नंबर को स्क्रिप्ट में डालने के लिए बेहतर लगता है, आदि) मेरे पास बस एक सामान्य विचलन है। जादू नंबर के लिए।)


3
बस हैश को याद रखने के लिए ;-) SHA1 ("ट्री 0 \ 0") = 4b825dc642cb6eb9a060e54bf8d69288fbee4904 (\ 0 NUL वर्ण) का उपयोग करें
थॉमस

4
@Thomas: git hash-object -t tree /dev/nullविधि (नीचे VonC के उत्तर से) का लाभ हार्ड-कोडिंग SHA-1 का नहीं है, उदाहरण के लिए SHA-2 के लिए git स्विच के कुछ भविष्य के संस्करण। (मैं जब कि हो सकता है भविष्यवाणी करने के लिए प्रयास करने के लिए नहीं जा रहा हूँ :-) यह SHA-2 के लिए मर्क्युरियल स्विच करने के लिए आसान होगा, क्योंकि वे इसके लिए कक्ष छोड़ दिया है।।)
torek

क्योंकि आप सही हैं, लेकिन यह "बेकार ज्ञान" का एक अच्छा टुकड़ा है और यह किसी और के लिए किसी भी मामले में मददगार हो सकता है ?!
थॉमस

2
@Thomas: हैश एल्गोरिथ्म बदलाव की तरह लग रहा है उम्मीद से जल्द हो सकता है । :-)
torek

"Git के कुछ भविष्य के संस्करण" के बारे में बोलते हुए, मुझे लगता है कि आप मेरे नवीनतम (Dec. 2017) में मेरे 2012 के उत्तर को संपादित करेंगे: stackoverflow.com/revisions/9766506/7
VonC

जवाबों:


104

यह सूत्र उल्लेख करता है:

यदि आपको खाली पेड़ sha1 याद नहीं है, तो आप इसे हमेशा प्राप्त कर सकते हैं:

git hash-object -t tree /dev/null

या, जैसा कि Ciro Santilli टिप्पणियों में प्रस्तावित करता है :

printf '' | git hash-object --stdin -t tree

या, जैसा कि यहां देखा गया है , कॉलिन स्किमफ्लिंग से :

git hash-object -t tree --stdin < /dev/null

इसलिए मुझे लगता है कि आपके खाली sha1 पेड़ के रूप में उस आदेश के परिणाम के साथ एक चर को परिभाषित करना सुरक्षित है (इसके बजाय "अच्छी तरह से ज्ञात मूल्य" का भरोसा करना)।

नोट: २.२५.१.१ (फरवरी २०२०) ने ९सी 29 ९ २ ९ ४ के लिए प्रस्ताव रखा :

empty_tree=$(git mktree </dev/null)
# Windows:
git mktree <NUL

और जोड़ता है:

एक ऐतिहासिक नोट के रूप में, अब जिस फ़ंक्शन को जाना जाता है repo_read_object_file()उसे 346245a1bb ("हार्ड-कोड द खाली ट्री ऑब्जेक्ट", 2008-02-13, Git v1.5-rc0 - मर्ज ) में खाली पेड़ सिखाया गया था , और फ़ंक्शन ज्ञात था। जैसा oid_object_info()कि c4d9986f5f (" sha1_object_info: cached_objectस्टोर की जाँच करें ", 2011-02-07, Git v1.7.4.1) में खाली पेड़ सिखाया गया था ।


ध्यान दें, आप देखेंगे कि SHA1 कुछ GitHub रेपो पर पॉप अप करता है जब लेखक चाहता है कि उसकी पहली कमिट खाली हो जाए (ब्लॉग पोस्ट देखें " मैं अपने गिट रिपॉजिटरी को कैसे इनिशियलाइज़ करता हूं "):

$ GIT_AUTHOR_DATE="Thu, 01 Jan 1970 00:00:00 +0000" GIT_COMMITTER_DATE="Thu, 01 Jan 1970 00:00:00 +0000" git commit --allow-empty -m 'Initial commit'

तुम्हे दूंगा:

खाली पेड़ SHA1

(पेड़ SHA1 देखें?)

आप उस खाली प्रतिबद्ध के ऊपर अपने मौजूदा इतिहास को भी रद्द कर सकते हैं (देखें " गिट: कैसे पहले के रूप में एक प्रतिबद्ध सम्मिलित करने के लिए, अन्य सभी को स्थानांतरित कर रहे हैं? "

दोनों ही मामलों में, आप उस खाली पेड़ के सटीक SHA1 मूल्य पर भरोसा नहीं करते हैं।
आप बस एक सबसे अच्छी प्रथा का पालन करते हैं, अपने रेपो को पहले खाली प्रतिबद्ध के साथ आरंभ करते हैं


ऐसा करने के लिए:

git init my_new_repo
cd my_new_repo
git config user.name username
git config user.email email@com

git commit --allow-empty -m "initial empty commit"

यह आपके रेपो, उपयोगकर्ता नाम, ईमेल, निर्माण की तारीख के लिए SHA1 के साथ एक कमिट उत्पन्न करेगा (मतलब कमेटी का SHA1 हर ​​बार अलग होगा)।
लेकिन उस प्रतिबद्ध द्वारा संदर्भित पेड़ 4b825dc642cb6eb9a060e54bf8d69288fbee4904, खाली पेड़ SHA1 होगा।

git log --pretty=raw

commit 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904      <====
author VonC <vonc@laposte.net> 1381232247 +0200
committer VonC <vonc@laposte.net> 1381232247 +0200

    initial empty commit

सिर्फ कमिट का पेड़ दिखाने के लिए (कमिटेड पेड़ SHA1 प्रदर्शित करें):

git show --pretty=format:%T 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
4b825dc642cb6eb9a060e54bf8d69288fbee4904

यदि वह प्रतिबद्ध है, तो एक खाली पेड़ को संदर्भित करना, वास्तव में आपकी पहली प्रतिबद्धता है, आप उस खाली पेड़ SHA1 को दिखा सकते हैं:

git log --pretty=format:%h --reverse | head -1 | xargs git show --pretty=format:%T
4b825dc642cb6eb9a060e54bf8d69288fbee4904

(और वह भी विंडोज पर काम करता है, गुन्नू ऑन विंडोज कमांड्स के साथ)


जैसा कि नीचे टिप्पणी की गई है , का उपयोग करते हुए git diff <commit> HEAD, यह आपकी सभी फ़ाइल को वर्तमान शाखा HEAD में दिखाएगा:

git diff --name-only 4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD

नोट: उस खाली पेड़ के मूल्य को औपचारिक रूप से परिभाषित किया गया है cache.h

#define EMPTY_TREE_SHA1_HEX \
    "4b825dc642cb6eb9a060e54bf8d69288fbee4904"

Git 2.16 (Q1 2018) के बाद से, यह एक संरचना में उपयोग किया जाता है जो अब (केवल) SHA1 से बंधा नहीं है, जैसा कि प्रतिबद्ध eb0ccfd में देखा गया है :

हैश एब्सट्रैक्शन का उपयोग करने के लिए खाली पेड़ और बूँद लुकअप स्विच करें

उपयोग में वर्तमान हैश एल्गोरिथ्म का प्रतिनिधित्व करने वाले अमूर्त का उपयोग करने के लिए empty_tree_oidऔर स्विच का उपयोग करें।empty_blob_oidcurrent_hash

और देखें " Git अधिक आधुनिक SHA का उपयोग क्यों नहीं करता है? ": यह SHA-2 है , क्योंकि Git 2.19 (Q3 2018)


2.25 Git (Q1 2020) के साथ, परीक्षण SHA-2 संक्रमण की तैयारी कर रहे हैं , और खाली पेड़ को शामिल कर रहे हैं।

देखें fa26d5e प्रतिबद्ध , cf02be8 प्रतिबद्ध , 38ee26b प्रतिबद्ध , प्रतिबद्ध 37ab8eb , प्रतिबद्ध 0370b35 , प्रतिबद्ध 0253e12 , प्रतिबद्ध 45e2ef2 , 79b0edc प्रतिबद्ध , प्रतिबद्ध 840624f , प्रतिबद्ध 32a6707 , प्रतिबद्ध 440bf91 , 0b408ca प्रतिबद्ध , प्रतिबद्ध 2eabd38 (28 अक्टू 2019), और 1bcef51 प्रतिबद्ध , प्रतिबद्ध ecde49b (05 अक्टूबर 2019) ब्रायन एमbk2204 द्वारा कार्लसन ( )
( जूनियो सी हमानोgitster द्वारा विलय - - में 28014c1 प्रतिबद्ध, 10 नवंबर 2019)

t/oid-info: खाली पेड़ और खाली बूँद मान जोड़ें

साइन-ऑफ-बाय: ब्रायन एम। कार्लसन

Testuite अंततः SHA-1 के अलावा अन्य एल्गोरिथ्म का उपयोग करके चलाना सीखेगा। इसकी तैयारी में, test_oidकार्यों के परिवार को सिखाएं कि खाली बूँद और खाली पेड़ के मूल्यों को कैसे देखा जाए ताकि उनका उपयोग किया जा सके।

तो t/oid-info/hash-infoअब शामिल हैं:

rawsz sha1:20
rawsz sha256:32

hexsz sha1:40
hexsz sha256:64

zero sha1:0000000000000000000000000000000000000000
zero sha256:0000000000000000000000000000000000000000000000000000000000000000

algo sha1:sha1
algo sha256:sha256

empty_blob sha1:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
empty_blob sha256:473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813

empty_tree sha1:4b825dc642cb6eb9a060e54bf8d69288fbee4904
empty_tree sha256:6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321

SHA2 " 6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321" नया SHA1 " 4b825dc642cb6eb9a060e54bf8d69288fbee4904" खाली पेड़ है।


@torek: मैंने कुछ उदाहरण जोड़ दिए हैं कि खाली पेड़ SHA1 को चित्रित करने के लिए पहली खाली प्रतिबद्ध सर्वोत्तम अभ्यास।
VonC

खैर, लक्ष्यों में से एक "खाली पेड़" हैश का उपयोग git diff-treeकुछ लिपियों में एक तर्क के रूप में कर रहा हूं जो मैं लिख रहा हूं। इस बात की कोई गारंटी नहीं है कि रेपो में एक प्रारंभिक खाली प्रतिबद्धता है। तो मैं सोच रहा था कि अगर ये स्क्रिप्ट किसी दिन टूट सकती है।
torek

1
यदि आप पास -wहो जाते हैं git hash-object, तो यह उस वस्तु को बनाएगा, जिसके विरुद्ध यह चल रहा है, और जो आप के खिलाफ चल रहे भंडार में खाली पेड़ को फिर से बनाएंगे, वह भविष्य में कभी दूर जाने के लिए था।
ज्वालामुखी

यदि आप रिबास का उपयोग करते हुए पहली प्रतिबद्धताओं से पहले जाना चाहते हैं, तो आप git rebase --root
GergelyPolonkai

1
या यदि आप जादू के बजाय पाइप के जादू को पसंद करते हैं /dev/null: printf '' | git hash-object --stdin -t tree:)
सिरो सेंटिल्ली prefer magic magic magic 事件 事件

3

मैंने हैश खोजने के दो अलग-अलग तरीकों से एक ब्लॉग पोस्ट लिखी है: http://colinschimmelfing.com/blog/gits-empty-tree/

यदि किसी कारण से इसे कभी भी बदलना पड़ा, तो आप इसे खोजने के लिए नीचे दिए गए दो तरीकों का उपयोग कर सकते हैं। हालाँकि, मुझे हैश इन .bashrc उपनामों इत्यादि का उपयोग करके बहुत आत्मविश्वास महसूस होगा, और मुझे नहीं लगता कि यह जल्द ही कभी भी बदलेगा।बहुत कम से कम यह शायद गिट की एक बड़ी रिलीज होगी।

दो तरीके हैं:

  1. उपरोक्त उत्तर: git hash-object -t tree --stdin < /dev/null
  2. बस एक खाली रेपो और फिर git write-treeउस नए रेपो में चल रहा है - हैश git राइट-ट्री द्वारा आउटपुट होगा।

के साथ कमांड चलाना –-stdinमुझे fatal: Cannot open '–-stdin': No such file or directorygit 2.7.2 के साथ देता है । हालाँकि, इसे बिना --stdinVonC के उत्तर के चलाने के रूप में हैश मान दिया गया है
sigy

यह उत्तर बहुत उपयोगी नहीं है अब ब्लॉग-पोस्ट मर चुका है। इसलिए हम आम तौर पर एसओ पर इन जवाबों का अनुमोदन नहीं करते हैं।
फिलिप व्हाइटहाउस

1
@PhilipWhitehouse ब्लॉग पोस्ट मृत नहीं है, लेकिन किसी भी आवरण में मैंने अपने उत्तर में दो तरीके शामिल किए हैं - मैं मानता हूं कि उन दो तरीकों को शामिल किए बिना, यह एक अच्छा जवाब नहीं होगा।
शिमी

3

यहां इस बात का जवाब है कि खाली पेड़ कैसे बनाए जाएं, इस मामले में भी जब भंडार पहले से ही खाली नहीं है। https://stackoverflow.com/a/14623458/9361507

लेकिन मैं "खाली" को टैग करना पसंद करता हूं, लेकिन शाखा नहीं। सरल तरीका है:

git tag empty $(git hash-object -t tree /dev/null)

क्योंकि टैग बिना प्रतिबद्ध किए सीधे पेड़-ईश को इंगित कर सकता है। अब कार्यशील ट्री में सभी फाइलें प्राप्त करने के लिए:

git diff --name-only empty

या स्टेट के साथ ही:

git diff --stat empty

सभी फाइलें अलग-अलग:

git diff empty

सभी फ़ाइलों में व्हाट्सएप की जाँच करें:

git diff --check empty

... लेकिन आपके टैग निर्माण में जादू नंबर का उपयोग करना सवाल के बहुत मामले के नीचे बस ब्रश करना है ( जादू नंबर SHA-1 का उपयोग नहीं करना)
RomainValeri

सच नहीं। मैंने ट्री-ईश ऑब्जेक्ट को इंगित करने के लिए टैग का उपयोग किया। अब तक इस ट्री-ईश को SHA-1 द्वारा परिभाषित किया गया है, भविष्य में इसे उदाहरण के लिए, SHA-256 और इसी तरह (रिपॉजिटरी माइग्रेशन के साथ) बदला जा सकता है। लेकिन टैग एक ही होगा। :) एक टैग की मुख्य विशेषता ऑब्जेक्ट को इंगित करना है। एक टैग SHA-1 का आंतरिक रूप से या कुछ और उपयोग कर सकता है, यह केवल गिट इंटर्नल का मामला है।
ओलेग

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

यदि आप इसे खाली ट्री हैश बनाने के तरीकों में से एक के साथ स्वचालित रूप से जोड़ते हैं, तो आप इसे भविष्य में प्रूफ कर सकते हैं (जैसा कि @RomainValeri से पता चलता है)। हालाँकि, अगर यह मेरे ऊपर था, git rev-parseतो नए झंडे या खोजशब्द या उन पंक्तियों के साथ कुछ होगा, (ए) खाली पेड़ हैश और (बी) नल-कम हैश। ये दोनों लिपियों में उपयोगी होंगे और प्रस्तावित SHA-256 परिवर्तनों से रक्षा करेंगे।
टॉरक

ओके, बदल गया। लेकिन यह "सबसे सरल तरीका" नहीं होगा। :)
ओलेग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.