১০.২ গিট ইন্টারনালস – গিট অবজেক্টস
গিট অবজেক্টস
গিট একটি কন্টেন্ট-এড্রেসেবল ফাইল সিস্টেম। এর দ্বারা আসলে কি বুঝায়? এর মানে হচ্ছে, গিট এর কোরে একটি কী-ভ্যালু ডাটা স্টোর আছে। এর দ্বারা বুঝা যায় যে, Git রিপোজিটেরির মধ্যে আপনি যে কোন ধরনের কন্টেন্ট রাখতে পারবেন, এর দ্বারা গিট একটি ইউনিক কী তৈরি করে থাকে যার মাধ্যমে ভবিষ্যতে এই কন্টেন্টগুলোকে পড়া যায়।
উদাহরণস্বরূপ, আমরা git hash-object প্লম্বিং কমান্ডটি দেখব। এটি কয়েকটি ডেটা গ্রহণ করে, সেগুলোকে .git/objects ডিরেক্টরিতে (অবজেক্ট ডেটাবেস) সংরক্ষণ করে এবং একটি ইউনিক কী তৈরি করে যা সেই ডাটা অবজেক্টগুলোর নির্দেশক হিসাবে কাজ করে।
প্রথমত, আমাদেরকে একটি Git রিপোজিটরি ইনিশিয়ালাইজ করতে হবে এবং গিট অবজেক্টের ভিতরে যে কিছু নেই এটি নিশ্চিত করতে হবে।
$ git init test
Initialized empty Git repository in /tmp/test/.git/
$ cd test
$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack
গিট অবজেক্ট ডিরেক্টরিটি ইনিশিয়ালাইজ করেছে এবং এতে প্যাক এবং ইনফো সাবডিরেক্টরি তৈরি করেছে, তবে এখানে কোনও ফাইল নেই। এখন, একটি নতুন ডেটা অবজেক্ট তৈরি করতে গিট হ্যাশ-অবজেক্ট ব্যবহার করা যাক এবং ম্যানুয়ালি এটিকে নতুন গিট ডাটাবেসে সংরক্ষণ করা যাক।
$ echo 'test content' | git hash-object -w --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4
সহজভাবে বলতে গেলে, git hash-object আপনার দেয়া কন্টটেন্টগুলোকে গ্রহণ করবে এবং এর পরিবর্তে আপনাকে একটি ইউনিক কী তৈরি করে দিবে এবং এই কন্টেন্টগুলোকে এই কী এর মাধ্যমেই Git database এ সংরক্ষণ করবে। শুধুমাত্র কী রিটার্ন না করে, অব্জেক্টিকে সঠিকভাবে ডাটাবেসে সংরক্ষণ করার জন্যেই -w অপশনটি ব্যবহার হয়ে থাকে। সবশেষে, –stdin অপশনটি git hash-objects ব্যবহার করে stdin থেকে কন্টেন্টগুলোকে বের করে নিয়ে আসে। অন্যথায়, এই কমান্ডের শেষে একটি ফাইল নেইম দেয়ার দরকার হয়, যে ফাইল থেকে পরবর্তীতে কন্টেন্টগুলোকে বের করে নিয়ে আসবে।
উপরোক্ত কমান্ড থেকে ফলাফলস্বরূপ ৪০ ক্যারাক্টারের একটি চেকসাম হ্যাশ তৈরি হয়। এটি একটি SHA-1 টাইপের হ্যাশ যেখানে একটি হেডারসহ আমাদের কন্টেটগুলো সংরক্ষিত থাকে। এখন আমরা দেখব কিভাবে git এই কাজটি করে।
$ find .git/objects -type .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
যদি অবজেক্ট ডিরেক্টরির দিকে তাকাই তাহলে দেখব যে এটি ঐ নতুন কন্টেন্টের জন্যে একটি নতুন ফাইল তৈরি করেছে। প্রাথমিকভাবে এভাবেই গিট, কন্টেন্টকে হেডারসহ SHA-1 চেকসামে একটি ফাইলে সংরক্ষণ করে থাকে। সাবডিরেক্টরিটির নামকরণ হয় SHA-1 এর প্রথম ২ ক্যারাক্টার নিয়ে এবং বাকি ৩৮ ক্যারাক্টার দিয়ে ফাইলের নামকরণ হয়।
একবার যখন অবজেক্ট ডাটাবেসে কন্টেন্ট থাকবে, git cat-file কমান্ডের মাধ্যমে সেই কন্টেন্টকে দেখা যাবে। git অবজেক্টগুলোকে দেখার জন্যে এই কমান্ডটি সর্বেসর্বা হিসাবে হিসাবে কাজ করে। cat-file কমান্ডটিতে -p যোগ করলে, এটি প্রথমে কন্টেন্টের ধরণ নির্ধারণ করে, তারপর এটিকে সঠিকভাবে প্রদর্শন করে।
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content
এখন আপনি গিটে যে কোন কন্টেন্ট যুক্ত করতে পারবেন এবং পুল ও করতে পারবেন। ফাইলের মধ্যেও এভাবে কন্টেন্ট যুক্ত করা যায়। উদাহরণস্বরূপ, একদম সহজ কিছু ভার্সন কন্ট্রোল করা যাক। প্রথমে, একটি ফাইল তৈরি করি এবং এই কন্টেন্টগুলোকে ডাটাবেসে সংরক্ষণ করি।
$ echo 'version 1' > test.txt
$ git hash-object -w test.txt
83baae61804e65cc73a7201a7252750c76066a30
এখন কিছু নতুন কন্টেন্ট যুক্ত করে সেটিকে ফাইলে সংরক্ষণ করি।
$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
ডাটাবেসের দিকে লক্ষ্য করলে দেখা যাবে যে, সেখানে নতুন ফাইলটির উভয় সংস্করণই সংরক্ষিত আছে।
$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3
এমতাবস্থায়, test.txt ফাইলের লোকাল কপিটি ডিলেট করে, git ব্যবহার করে পুনরায় গিট ডাটাবেস থেকে সেটিকে পুনুরুদ্ধার করার যাবে, যার প্রথম সংস্করণ আগে সংরক্ষিত ছিল।
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
$ cat test.txt
version 1
অথবা দ্বিতীয় সংস্করণঃ
$ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt
$ cat test.txt
version 2
কিন্তু, ফাইলের প্রতিটি সংস্করণের জন্যে SHA-1 এর মান মনে রাখাটা বাস্তবসম্ভত না। এবং সিস্টেমে কন্টেন্ট ব্যতীত কোন ফাইলের নাম সংরক্ষিত হয় না। এই ধরণের অবজেক্টকে blob বলা হয়। git cat-file -t এর মাধ্যমে গিট থেকে যে কোন অবজেক্টের টাইপ এবং এটির SHA-1 কী পাওয়া যায়।
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
blob
ট্রি অবজেক্ট
পরবর্তী ধরণের গিট অবজেক্টটি আমরা বিশ্লেষণ করব যা হচ্ছে ট্রি , যা ফাইলের নাম সংরক্ষণের সমস্যার সমাধান করে এবং আপনাকে ফাইলগুলির একটি গ্রুপকে একসাথে সংরক্ষণ করার অনুমতি দেয়। গিট ইউনিক্স ফাইল সিস্টেমের মতো একটি পদ্ধতিতে কনটেন্ট স্টোর করে, তবে কিছুটা সহজভাবে।সমস্ত কনটেন্ট গুলো ট্রি এবং ব্লব অবজেক্ট হিসাবে সংরক্ষণ করা হয়, UNIX ডিরেক্টরি এন্ট্রির সাথে সম্পর্কিত ট্রি এবং ইনোড বা ফাইলের কনটেন্ট সাথে কম বা বেশি সুবিধাজনক ব্লব সহ।
একটি একক ট্রি অবজেক্টে এক বা একাধিক এন্ট্রি থাকে, যার প্রতিটি হল একটি ব্লব বা সাবট্রির SHA-1 হ্যাশ এর সাথে যুক্ত মোড, টাইপ এবং ফাইলের নাম। উদাহরণস্বরূপ, ধরা যাক আপনার কাছে একটি প্রজেক্ট আছে যেখানে সাম্প্রতিকতম ট্রি দেখতে এরকম কিছুটা এমন দেখাচ্ছে:
$ git cat-file -p master^{tree}
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib
master^{tree} সিনট্যাক্স ট্রি অবজেক্টকে নির্দিষ্ট করে যা আপনার মাস্টার ব্র্যাঞ্চের শেষ কমিট দ্বারা নির্দেশিত হয়। লক্ষ্য করুন যে lib সাবডিরেক্টরি একটি ব্লব নয় বরং অন্য ট্রি এর নির্দেশক:
$ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
100644 blob 47c6340d6459e05787f644c2447d2595f5d3a54b simplegit.rb
আপনি কোন শেল ব্যবহার করেন তার উপর নির্ভর করে,master^{tree} সিনট্যাক্স ব্যবহার করার সময় আপনি এরর এর সম্মুখীন হতে পারেন।
উইন্ডোজের সিএমডিতে, ^ অক্ষরটি escaping জন্য ব্যবহার করা হয়, তাই এটি এড়াতে আপনাকে দুইবার ব্যবহার করতে হবে: git cat-file -p master^^{tree}।
পাওয়ারশেল ব্যবহার করার সময়, প্যারামিটারটিকে ভুলভাবে পার্স করা এড়াতে {} অক্ষর ব্যবহার করা প্যারামিটারগুলিকে কোট করতে হবে: git cat-file -p ‘master^{tree}’।
গিট যে ডেটা সঞ্চয় করছে তা অনেকটা এরকম দেখায়:
আপনি মোটামুটি সহজেই আপনার নিজের ট্রি তৈরি করতে পারেন। গিট সাধারণত আপনার স্টেজিং এরিয়া বা ইন্ডেক্স অবস্থা নেয় এবং সেটা থেকে ট্রি এর অবজেক্টের একটি সিরিজ লিখে একটি ট্রি তৈরি করে। সুতরাং, একটি ট্রি অবজেক্ট তৈরি করতে, আপনাকে প্রথমে কিছু ফাইল স্টেজ করে একটি ইন্ডেক্স সেট আপ করতে হবে।
একটি একক এন্ট্রি–আপনার test.txt ফাইলের প্রথম সংস্করণ –এর সাহায্যে একটি ইন্ডেক্স তৈরি করতে আপনি প্লাম্বিং কমান্ড git update-index ব্যবহার করতে পারেন। আপনি একটি নতুন স্টেজিং এলাকায় test.txt ফাইলের আগের সংস্করণটি কৃত্রিমভাবে যুক্ত করতে এই কমান্ডটি ব্যবহার করেন। আপনাকে অবশ্যই –add বিকল্পটি পাস করতে হবে কারণ ফাইলটি আপনার স্টেজিং এরিয়াতে এখনও বিদ্যমান নেই (এখনও আপনার স্টেজিং এরিয়া সেট আপ করা হয়নি) এবং –cacheinfo কারণ আপনি যে ফাইলটি যোগ করছেন সেটি আপনার ডিরেক্টরিতে নেই কিন্তু আপনার ডাটাবেসে আছে। তারপর, আপনি মোড, SHA-1, এবং ফাইলের নাম নির্দিষ্ট করুন:
$ git update-index --add --cacheinfo 100644 \
83baae61804e65cc73a7201a7252750c76066a30 test.txt
এই ক্ষেত্রে, আপনি 100644 এর একটি মোড নির্দিষ্ট করছেন, যার মানে এটি একটি সাধারণ ফাইল। অন্যান্য বিকল্পগুলি হল 100755, যার মানে এটি একটি এক্সিকিউটেবল ফাইল; এবং 120000, যা একটি সিম্বোলিক লিঙ্ক নির্দিষ্ট করে। মোডটি সাধারণ ইউনিক্স মোড থেকে নেওয়া তবে এটি অনেক কম ফ্লেক্সিবল — এই তিনটি মোডই একমাত্র যা গিট-এ ফাইলের (ব্লব) জন্য ভেলিড (যদিও অন্যান্য মোডগুলি ডিরেক্টরি এবং সাবমডিউলগুলির জন্য ব্যবহৃত হয়)।
এখন, আপনি ট্রি অবজেক্টে স্টেজিং এরিয়া লিখতে git write-tree ব্যবহার করতে পারেন। কোন -w বিকল্পের প্রয়োজন নেই — এই কমান্ডটিকে কল করা হলে স্বয়ংক্রিয়ভাবে ইনডেক্সের অবস্থা থেকে একটি ট্রি অবজেক্ট তৈরি করবে যদি সেই ট্রি এখনও বিদ্যমান না থাকে:
$ git write-tree
d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test.txt
আপনি git cat-file কমান্ড ব্যবহার করে যাচাই করতে পারেন যে এটি একটি ট্রি অবজেক্ট যা আপনি আগে দেখেছিলেন:
$ git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579
tree
আপনি এখন একটি নতুন ট্রি তৈরি করবেন test.txt এর দ্বিতীয় সংস্করণ এবং একটি নতুন ফাইলের ব্যবহার করে :
$ echo 'new file' > new.txt
$ git update-index --cacheinfo 100644 \
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
$ git update-index --add new.txt
আপনার স্টেজিং এরিয়াতে test.txt এর নতুন সংস্করণের পাশাপাশি নতুন ফাইল new.txt রয়েছে। সেই ট্রিটি লিখুন (স্টেজিং এলাকার অবস্থা রেকর্ড করা বা একটি ট্রির অব্জেক্টের ইন্ডেক্স ) এবং দেখুন এটি কেমন দেখাচ্ছে:
$ git write-tree
0155eb4229851634a0f03eb265b69f5a2d56f341
$ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
লক্ষ্য করুন যে এই ট্রিতে উভয় ফাইল এন্ট্রি রয়েছে এবং এটিও যে test.txt SHA-1 হল আগের (1f7a7a) “সংস্করণ 2” SHA-1। শুধু দেখার জন্য, আপনি এটিতে একটি সাবডিরেক্টরি হিসাবে প্রথম ট্রি টা যুক্ত করতে পারেন। আপনি git read-tree কল করে আপনার স্টেজিং এরিয়াতে ট্রি রিড করতে পারেন। এই ক্ষেত্রে, আপনি এই কমান্ডের সাথে –prefix ব্যবহার করে একটি সাবট্রি হিসাবে আপনার স্টেজিং এরিয়াতে বিদ্যমান ট্রি রিড করতে পারেন:
$ git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git write-tree
3c4e9cd789d88d8d89c1073707c3585e41b0e614
$ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614
040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 bak
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
আপনি যদি নতুন ট্রি থেকে একটি ওয়ার্কিং ডাইরেক্টরি তৈরি করেন যা আপনি এইমাত্র লিখেছেন, তাহলে আপনি ওয়ার্কিং ডাইরেক্টরির শীর্ষ স্তরে দুটি ফাইল পাবেন এবং bak নামে একটি সাবডিরেক্টরি পাবেন যেখানে test.txt ফাইলের প্রথম সংস্করণ রয়েছে। আপনি এই স্ট্রাকচারগুলির জন্য গিট যে ডেটা ধারণ করেছেন তা এইরকম হিসাবে ভাবতে পারেন:
কমিট অবজেক্ট
আপনি যদি উপরের সবগুলো করে থাকেন, তাহলে আপনার কাছে এখন তিনটি ট্রি আছে যা আপনার প্রজেক্টের বিভিন্ন স্ন্যাপশটকে প্রতিনিধিত্ব করে, কিন্তু আগের সমস্যাটি রয়ে গেছে: স্ন্যাপশটগুলি স্মরণ করার জন্য আপনাকে অবশ্যই তিনটি SHA-1 মান মনে রাখতে হবে । এবং কে স্ন্যাপশটগুলি সংরক্ষণ করেছে, কখন সেগুলি সংরক্ষণ করা হয়েছিল বা কেন সেগুলি সংরক্ষণ করা হয়েছিল সে সম্পর্কেও আপনার কাছে কোন তথ্য নেই৷ এটি হল মৌলিক তথ্য যা কমিট অবজেক্ট সঞ্চয় করে।
একটি কমিট অবজেক্ট তৈরি করতে, আপনি commit-tree কল করুন এবং একটি SHA-1 নির্দিষ্ট করুন এবং কোন কমিট অবজেক্ট, যদি থাকে, সরাসরি এটির আগে। আপনি যে প্রথম ট্রি টি লিখেছেন তা দিয়ে শুরু করুন:
$ echo 'First commit' | git commit-tree d8329f
fdf4fc3344e67ab068f836878b6c4951e3b15f3d
ভিন্ন creation time এবং author ডেটার কারণে আপনি একটি ভিন্ন হ্যাশ পাবেন। নীতিগতভাবে যে কোনও কমিট অবজেক্টকে সঠিকভাবে সেই ডেটা দিয়ে পুনরুত্পাদন করা যেতে পারে, এই বইটিতে মুদ্রিত কমিট হ্যাশগুলি প্রদত্ত কমিটগুলির সাথে সঙ্গতিপূর্ণ নাও হতে পারে। এই অধ্যায়ে আপনার নিজের চেকসামগুলির সাথে কমিট এবং ট্যাগ হ্যাশগুলি প্রতিস্থাপন করুন।
এখন আপনি git cat-file এর সাথে আপনার নতুন কমিট অবজেক্টটি মিলিয়ে দেখতে পারেন:
$ git cat-file -p fdf4fc3
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author Scott Chacon 1243040974 -0700
committer Scott Chacon 1243040974 -0700
First commit
একটি commit object এর বিন্যাস সহজ: এটি সেই সময়ে প্রকল্পের স্ন্যাপশটের জন্য শীর্ষ-স্তরের ট্রি নির্দিষ্ট করে; parent commit যদি থাকে (উপরে বর্ণিত commit এর কোনো প্যারেন্ট নেই); author/committer তথ্য (যা আপনার user.name এবং user.email কনফিগারেশন সেটিংস এবং একটি timestamp ব্যবহার করে); তারপর একটি ফাঁকা লাইন, এবং তারপর কমিট বার্তা ।
এর পরে, আপনি অন্য দুটি কমিট অবজেক্ট লিখবেন, প্রতিটি তার আগে সরাসরি আসা কমিটকে উল্লেখ করে:
$ echo 'Second commit' | git commit-tree 0155eb -p fdf4fc3
cac0cab538b970a37ea1e769cbbde608743bc96d
$ echo 'Third commit' | git commit-tree 3c4e9c -p cac0cab
1a410efbd13591db07496601ebc7a059dd55cfe9
প্রতিটি কমিট অবজেক্ট আপনার তৈরি করা তিনটি স্ন্যাপশট ট্রি কে নির্দেশ করে। আপনার কাছে এখন একটি আসল গিট হিস্টোরি রয়েছে যা আপনি git log কমান্ড দিয়ে দেখতে পারেন, যদি আপনি শেষ কমিট এর SHA-1-এ রান করেন :
$ git log --stat 1a410e
commit 1a410efbd13591db07496601ebc7a059dd55cfe9
Author: Scott Chacon
Date: Fri May 22 18:15:24 2009 -0700
Third commit
bak/test.txt | 1 +
1 file changed, 1 insertion(+)
commit cac0cab538b970a37ea1e769cbbde608743bc96d
Author: Scott Chacon
Date: Fri May 22 18:14:29 2009 -0700
Second commit
new.txt | 1 +
test.txt | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d
Author: Scott Chacon
Date: Fri May 22 18:09:34 2009 -0700
First commit
test.txt | 1 +
1 file changed, 1 insertion(+)
অসাধারণ, আপনি ফ্রন্ট এন্ড কমান্ড ব্যবহার না করেই একটি গিট হিস্টোরি তৈরি করেছেন লো-লেভেল অপারেশন কমান্ড ব্যবহার করেই ! এটাই গিট করে থাকে যখন আপনি git add এবং git commit কমান্ড রান করে থাকেন। এটি blob স্টোরে ফাইলের পরিবর্তন সঞ্চয় করে, ইনডেক্স আপডেট রাখে, ট্রি ম্যানেজ করে, এবং কমিট অবজেক্ট ও তাদের আগে আসা কমিট গুলোর রেফারেন্স ম্যানেজ করে। সাধারণত, এই তিনটি মুল অবজেক্ট – blob, tree, এবং commit – গিট আলাদা আলাদা ফাইলে ম্যানেজ করে যা .git/objects ডিরেক্টরিতে থাকে । নীচের উদাহরণটিতে ডিরেক্টরির সমস্ত অবজেক্ট দেখান হয়েছে, তার সাথে মন্তব্য করা হয়েছে:
$ find .git/objects -type f
.git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2
.git/objects/1a/410efbd13591db07496601ebc7a059dd55cfe9 # commit 3
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a # test.txt v2
.git/objects/3c/4e9cd789d88d8d89c1073707c3585e41b0e614 # tree 3
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt v1
.git/objects/ca/c0cab538b970a37ea1e769cbbde608743bc96d # commit 2
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 # 'test content'
.git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # tree 1
.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt
.git/objects/fd/f4fc3344e67ab068f836878b6c4951e3b15f3d # commit 1
আপনি যদি সমস্ত অভ্যন্তরীণ পয়েন্টার অনুসরণ করেন তবে আপনি এইরকম একটি অবজেক্ট গ্রাফ পাবেন:
অবজেক্ট স্টোরেজ
আমরা আগে উল্লেখ করেছি যে, আপনার গিট অবজেক্ট ডাটাবেসে প্রতিটি কমিট অবজেক্টের সাথে একটি শিরোনাম সংরক্ষিত আছে। গিট কীভাবে তার অবজেক্টগুলিকে সঞ্চয় করে তা দেখতে এক মিনিট সময় নেওয়া যাক। আপনি দেখতে পাবেন কিভাবে একটি ব্লব অবজেক্ট সঞ্চয় করতে হয় — এই ক্ষেত্রে, স্ট্রিং “what is up, doc?” – Ruby স্ক্রিপ্টিং ল্যাঙ্গুয়েজ দিয়ে এড করি।
আপনি irb কমান্ডের দিয়ে ইন্টারেক্টিভ Ruby মোড শুরু করতে পারেন:
$ irb
>> content = "what is up, doc?"
=> "what is up, doc?"
গিট প্রথমে একটি header তৈরি করে যা অবজেক্টের ধরন সনাক্ত করে- এই ক্ষেত্রে, এটি একটি ব্লব। এই header এর প্রথম অংশে, গিট একটি স্পেস এড করে এবং এর পরে null বাইট এড করে।
>> header = "blob #{content.bytesize}\0"
=> "blob 16\u0000"
গিট header এবং মূল কনটেন্ট সংযুক্ত করে, তারপর সেই নতুন কনটেন্ট এর SHA-1 চেকসাম এড করে। আপনি Ruby তে একটি স্ট্রিং এর SHA-1 মান গণনা করতে পারেন তার জন্য আপনার প্রয়োজন একটি SHA1 ডাইজেস্ট লাইব্রেরি এবং require কমান্ড । তারপরে স্ট্রিং সহ Digest::SHA1.hexdigest() কল করুন:
>> store = header + content
=> "blob 16\u0000what is up, doc?"
>> require 'digest/sha1'
=> true
>> sha1 = Digest::SHA1.hexdigest(store)
=> "bd9dbf5aae1a3862dd1526723246b20206e5fc37"
আসুন এটিকে git hash-object আউটপুটের সাথে তুলনা করি। এখানে echo -n ব্যবহার করে নতুন লাইন যোগ করা প্রতিরোধ করলাম ।
$ echo -n "what is up, doc?" | git hash-object --stdin
Bd9dbf5aae1a3862dd1526723246b20206e5fc37
গিট zlib ব্যবহার করে কমপ্রেস করে যা আমরা Ruby zlib লাইব্রেরি ব্যবহার করে করতে পারি। প্রথমে zlib লাইব্রেরি ইম্পোরট করা লাগবে, তারপর রান করুন Zlib::Deflate.deflate()
>> require 'zlib'
=> true
>> zlib_content = Zlib::Deflate.deflate(store)
=> "x\x9CK\xCA\xC9OR04c(\xCFH,Q\xC8,V(-\xD0QH\xC9O\xB6\a\x00_\x1C\a\x9D"
অবশেষে, আপনি zlib-deflated কনটেন্ট লিখবেন একটি ডিস্ক অবজেক্টে। আপনি যে অবজেক্টটি লিখতে চান তার পাথ নির্ধারণ করবেন (SHA-1 এর প্রথম দুটি অক্ষর হল সাবডিরেক্টরি নাম, এবং শেষ 38টি অক্ষর সেই ডিরেক্টরির মধ্যে ফাইলের নাম)। Ruby তে, আপনি FileUtils.mkdir_p() ফাংশন ব্যবহার করতে পারেন সাবডিরেক্টরি তৈরি করতে, যদি এটি বিদ্যমান না থাকে। তারপরে, File.open() দিয়ে ফাইলটি খুলুন এবং write() কল দিয়ে ফাইলটিতে zlib-compressed কনটেন্ট টি লিখুন:
>> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38]
=> ".git/objects/bd/9dbf5aae1a3862dd1526723246b20206e5fc37"
>> require 'fileutils'
=> true
>> FileUtils.mkdir_p(File.dirname(path))
=> ".git/objects/bd"
>> File.open(path, 'w') { |f| f.write zlib_content }
=> 32
চলুন, কনটেন্ট এর অবজেক্টটি git cat-file দিয়ে চেক করি
---
$ git cat-file -p bd9dbf5aae1a3862dd1526723246b20206e5fc37
what is up, doc?
---
এটাই – আপনি একটি গিট ব্লব অবজেক্ট তৈরি করেছেন।
সমস্ত গিট অবজেক্ট একইভাবে সংরক্ষিত হয়, শুধুমাত্র বিভিন্ন মাধ্যমে এটি হতে পারে – যেমন, স্ট্রিং ব্লবের পরিবর্তে, হেডারটি কমিট বা ট্রি দিয়ে শুরু হবে। এছাড়াও, যদিও ব্লব অবজেক্ট যেকোনো কিছু হতে পারে, কমিট এবং ট্রি কনটেন্ট খুব নির্দিষ্টভাবে ফরম্যাট করা।