গিট ছাড়াই কোনও ফাইলকে কীভাবে একটি গিট এসএএএ 1 অর্পণ করবেন?


138

আমি যখন বুঝতে পারি যে যখন গিট কোনও ফাইলকে একটি SHA1 হ্যাশ দেয় তখন এই SHA1 এর বিষয়বস্তুর উপর ভিত্তি করে ফাইলটি অনন্য।

ফলস্বরূপ যদি কোনও ফাইল একটি সংগ্রহস্থল থেকে অন্য SHA1 এ ফাইলের জন্য স্থানান্তরিত করে তবে ফাইলের বিষয়বস্তু পরিবর্তন হয়নি।

গিট কীভাবে SHA1 হজম গণনা করে? এটি কি সম্পূর্ণ সঙ্কুচিত ফাইল সামগ্রীতে তা করে?

আমি গিটের বাইরে এসএএএল 1 নির্ধারণ করতে চাই।




উত্তর:


255

এইভাবেই গিট কোনও ফাইলের জন্য SHA1 গণনা করে (বা গিট শর্তে একটি "ব্লব"):

sha1("blob " + filesize + "\0" + data)

সুতরাং আপনি সহজেই গিট ইনস্টল না করে নিজেই এটি গণনা করতে পারেন। মনে রাখবেন যে "\ 0" হ'ল নুয়াল-বাইট, একটি দ্বি-চরিত্রের স্ট্রিং নয়।

উদাহরণস্বরূপ, একটি খালি ফাইলের হ্যাশ:

sha1("blob 0\0") = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"

$ touch empty
$ git hash-object empty
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391

আরেকটি উদাহরণ:

sha1("blob 7\0foobar\n") = "323fae03f4606ea9991df8befbb2fca795e648fa"

$ echo "foobar" > foo.txt
$ git hash-object foo.txt 
323fae03f4606ea9991df8befbb2fca795e648fa

এখানে পাইথন বাস্তবায়ন:

from hashlib import sha1
def githash(data):
    s = sha1()
    s.update("blob %u\0" % len(data))
    s.update(data)
    return s.hexdigest()

এই উত্তর পাইথন 2 ধরে? পাইথন 3 এ চেষ্টা করার পরে আমি TypeError: Unicode-objects must be encoded before hashingপ্রথম s.update()লাইনে একটি ব্যতিক্রম পাই ।
বুথ

3
পাইথন 3 এর সাথে আপনাকে ডেটা এনকোড করতে হবে: s.update(("blob %u\0" % filesize).encode('utf-8'))এড়ানোর জন্য TypeError
মার্ক বুথ

ইউটিএফ -8 হিসাবে এনকোডিংটি কাজ করবে, তবে সম্ভবত এটি প্রথমে বাইট স্ট্রিং থেকে এটি তৈরি করা ভাল (utf-8 এনকোডিং কাজ করে কারণ ইউনিকোডের কোনও অক্ষরই অ-ASCII নয়)।
torek

একটি অতিরিক্ত বিষয় উল্লেখযোগ্য যা হ'ল গিট হ্যাশ-অবজেক্টটি "\ r \ n" কে "he n" ডেটাযুক্ত সামগ্রীর সাথে প্রতিস্থাপন করবে বলে মনে হয়। এটি "\ r" এর পুরোপুরি খুব ভালভাবে কেটে ফেলতে পারে, আমি এটি চেক করি নি।
user420667

1
আমি এখানে পাইথন 2 + 3 (এক সাথে উভয়) ফাইল এবং ট্রি হ্যাশ জেনারেটরের প্রয়োগ এখানে করেছি: github.com/chris3torek/scriptts/blob/master/githash.py ( ট্রি হ্যাশ ডিরেক্টরি ডিরেক্টরি পড়ে)।
টোকর

17

একটু গুডি: শেল

echo -en "blob ${#CONTENTS}\0$CONTENTS" | sha1sum

1
আমি echo -en "blob ${#CONTENTS}\0$CONTENTS" | sha1sumআউটপুট তুলনা করছি git hash-object path-to-fileএবং তারা বিভিন্ন ফলাফল উত্পাদন। যাইহোক, echo -e ...সঠিক ফল ছাড়া সেখানে একটি trailing হয় - ( git hash-objectউৎপন্ন কোন চিহ্ন অক্ষর)। এটা কি আমার কিছু চিন্তা করা উচিত?
হতাশ

2
@ ফ্রাস্ট্রেটড উইথফর্মস ডিজাইনার: এই স্ট্যান্ডিনের থেকে হ্যাশ ফাইল থেকে নয় যদি কোনও ফাইল থেকে গণনা করা -হয় sha1sumতবে পিছনে ব্যবহার করা হবে। চিন্তার কিছু. যদিও অদ্ভুত জিনিসটি -n, এটিকে সাধারণত প্রতিধ্বনির সাহায্যে যুক্ত হওয়া নিউলাইনটি দমন করা উচিত। কোনও সুযোগে আপনার ফাইলটির কোনও ফাঁকা শেষ লাইন আছে, যা আপনি আপনার CONTENTSভেরিয়েবলটি যুক্ত করতে ভুলে গেছেন ?
নিটল

হ্যাঁ, আপনি ঠিক বলেছেন। এবং আমি ভেবেছিলাম যে sha1sum এর আউটপুট কেবল হ্যাশ হওয়া উচিত , তবে সেড বা কোনও কিছু দিয়ে এটি মুছে ফেলা কঠিন নয়।
হতাশ

@ ফ্রাস্ট্রেটেড উইথফর্মস ডিজাইনার: আপনি যদি আরও প্রসেস এবং cat file | sha1sumsha1sum file
পাইপিংয়ের

8

আপনি যদি গিট ইনস্টল না করে থাকেন তবে এটি সহজেই গণনা করার জন্য আপনি ব্যাশ শেল ফাংশন তৈরি করতে পারেন।

git_id () { printf 'blob %s\0' "$(ls -l "$1" | awk '{print $5;}')" | cat - "$1" | sha1sum | awk '{print $1}'; }

1
একটি সংক্ষিপ্ত বিট: (stat --printf="blob %s\0" "$1"; cat "$1") | sha1sum -b | cut -d" " -f1
স্কুবার্থ

4

গিট-হ্যাশ-অবজেক্টের জন্য ম্যান পৃষ্ঠাটি একবার দেখুন । আপনি এটি কোনও নির্দিষ্ট ফাইলের গিট হ্যাশ গণনা করতে ব্যবহার করতে পারেন। আমি মনে করি যে গিটটি হ্যাশ অ্যালগরিদমের মধ্যে কেবলমাত্র ফাইলের বিষয়বস্তুগুলির চেয়ে বেশি ফিড দেয়, তবে আমি নিশ্চিতভাবে জানি না এবং এটি অতিরিক্ত ডেটা ফিড করলে আমি জানি না এটি কী।


2
/// Calculates the SHA1 for a given string
let calcSHA1 (text:string) =
    text 
      |> System.Text.Encoding.ASCII.GetBytes
      |> (new System.Security.Cryptography.SHA1CryptoServiceProvider()).ComputeHash
      |> Array.fold (fun acc e -> 
           let t = System.Convert.ToString(e, 16)
           if t.Length = 1 then acc + "0" + t else acc + t) 
           ""
/// Calculates the SHA1 like git
let calcGitSHA1 (text:string) =
    let s = text.Replace("\r\n","\n")
    sprintf "blob %d%c%s" (s.Length) (char 0) s
      |> calcSHA1

এটি F # তে একটি সমাধান।


আমি এখনও আমলাটগুলি নিয়ে সমস্যায় পড়েছি: ক্যালজিটএসএইচ 1 ("ü")। কোনও ধারণা কীভাবে গিট হ্যাশ-অবজেক্ট আমলাতকে পরিচালনা করে?
forki23

এটি একটি ব্লাস্টবকে বাইটাস্টিম হিসাবে পরিচালনা করবে, তার অর্থ সম্ভবত দৈর্ঘ্য 2 (ইউনিকোড) থাকবে, F♯ এর দৈর্ঘ্যের সম্পত্তি দৈর্ঘ্য 1 ফিরে আসবে (কারণ এটি কেবল একটি দৃশ্যমান চরিত্র)
নিটল

কিন্তু System.Text.Encoding.ASCII.GetBytes ("ü") 1 টি উপাদান সহ একটি বাইট অ্যারে প্রদান করে।
forki23

ইউটিএফ 8 এবং 2 টি স্ট্রিংয়ের দৈর্ঘ্যের হিসাবে ব্যবহার করা একটি বাইট অ্যারে দেয়: [98; 108; 111; 98; 32; 50; 0; 195; 188] এবং তার জন্য 99fe40df261f7d4afd1391fe2739b2c7466fe968 এর একটি SHA1। যা গিট এসএএএ 1ও নয়।
forki23

1
চরিত্রের স্ট্রিংগুলিতে আপনার কখনই ডাইজেট প্রয়োগ করা উচিত নয়। পরিবর্তে আপনাকে অবশ্যই এগুলি প্রয়োগ করতে হবে বাইট স্ট্রিংগুলিতে (বাইট অ্যারে) যা আপনি স্বতন্ত্র এনকোডিং ব্যবহার করে অক্ষরের স্ট্রিংকে বাইটে রূপান্তরিত করে পেতে পারেন।
ডলমেন

2

পূর্ণ পাইথন 3 বাস্তবায়ন:

import os
from hashlib import sha1

def hashfile(filepath):
    filesize_bytes = os.path.getsize(filepath)

    s = sha1()
    s.update(b"blob %u\0" % filesize_bytes)

    with open(filepath, 'rb') as f:
        s.update(f.read())

    return s.hexdigest() 

2
আপনি যা চান তা হ'ল ASCII এনকোডিং। ইউটিএফ 8 কেবলমাত্র এখানে কাজ করে কারণ এটি ASCII এর সাথে সামঞ্জস্যপূর্ণ এবং "ব্লব x \ 0" এ কেবল কোডের সাথে অক্ষরগুলি রয়েছে <= 127.
ফার্ডিনান্ড বায়ার

1

পার্লে:

#!/usr/bin/env perl
use Digest::SHA1;

my $content = do { local $/ = undef; <> };
print Digest::SHA1->new->add('blob '.length($content)."\0".$content)->hexdigest(), "\n";

শেল কমান্ড হিসাবে:

perl -MDigest::SHA1 -E '$/=undef;$_=<>;say Digest::SHA1->new->add("blob ".length()."\0".$_)->hexdigest' < file


1

রুবি ব্যবহার করে আপনি এরকম কিছু করতে পারেন:

require 'digest/sha1'

def git_hash(file)
  data = File.read(file)
  size = data.bytesize.to_s
  Digest::SHA1.hexdigest('blob ' + size + "\0" + data)
end

1

একটি সামান্য বাশ স্ক্রিপ্ট যাতে অভিন্ন আউটপুট তৈরি করতে হবে git hash-object:

#!/bin/sh
( 
    echo -en 'blob '"$(stat -c%s "$1")"'\0';
    cat "$1" 
) | sha1sum | cut -d\  -f 1

0

জাভাস্ক্রিপ্টে

const crypto = require('crypto')
const bytes = require('utf8-bytes')

function sha1(data) {
    const shasum = crypto.createHash('sha1')
    shasum.update(data)
    return shasum.digest('hex')
}

function shaGit(data) {
    const total_bytes = bytes(data).length
    return sha1(`blob ${total_bytes}\0${data}`)
}

-4

এটি লক্ষণীয় আকর্ষণীয় যে স্পষ্টতই গিট ডেটা হ্যাশ হওয়ার আগে ডেটার শেষে একটি নিউলাইন চরিত্র যুক্ত করে। "হ্যালো ওয়ার্ল্ড!" ব্যতীত কিছুই নেই এমন একটি ফাইল 980a0d5 ... এর একটি ব্লব হ্যাশ পেয়েছে ... যা এইটির মতোই:

$ php -r 'echo sha1("blob 13" . chr(0) . "Hello World!\n") , PHP_EOL;'

4
সেই নিউলাইনটি আপনার পাঠ্য সম্পাদক দ্বারা যুক্ত করা হচ্ছে, এটি দ্বারা নয় git hash-object। নোট করুন যে echo "Hello World!" | git hash-object --stdinদেয় 980a0d5..., যখন ব্যবহার echo -nএকটি হ্যাশ দেয় c57eff5...পরিবর্তে।
বিডেশম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.