2015-03-17 24 views
12

Git commit ID được tạo ra như thế nào để nhận dạng duy nhất các cam kết?Git - ID cam kết git là gì?

Ví dụ: 521747298a3790fde1710f3aa2d03b55020575aa

Làm thế nào nó hoạt động? Chúng chỉ là duy nhất cho mỗi dự án? hoặc cho kho git trên toàn cầu?

+0

Xem http://git-scm.com/book/en/v2/Getting-Started-Git-Basics#Git-Has-Integrity – Jubobs

+4

Không chắc chắn lý do bạn bị giảm giá. Tôi thấy chủ đề này rất thú vị. –

Trả lời

16

ID cam kết Git là SHA-1 hash của mọi điều quan trọng về cam kết. Tôi sẽ không liệt kê tất cả, nhưng đây là những điều quan trọng ...

  • Nội dung, tất cả, không chỉ khác biệt.
  • Ngày cam kết.
  • Tên và địa chỉ email của người gửi.
  • Thông báo tường trình.
  • ID của (những) cam kết trước đó.

Thay đổi bất kỳ thay đổi nào và ID cam kết thay đổi. Và có, cùng một cam kết với các thuộc tính giống nhau sẽ có cùng một ID trên một máy khác. Điều này phục vụ ba mục đích. Đầu tiên, nó có nghĩa là hệ thống có thể cho biết liệu một cam kết đã bị giả mạo. Nó được nướng ngay vào kiến ​​trúc.

Thứ hai, người ta có thể nhanh chóng so sánh các cam kết chỉ bằng cách xem ID của họ. Điều này làm cho các giao thức mạng của Git rất hiệu quả. Bạn muốn so sánh hai cam kết để xem chúng có giống nhau hay không? Không phải gửi toàn bộ khác biệt, chỉ cần gửi ID.

Thứ ba và đây là thiên tài, hai cam kết có cùng số ID có cùng một lịch sử. Đó là lý do tại sao ID của các cam kết trước đó là một phần của hàm băm. Nếu nội dung của một cam kết là như nhau nhưng cha mẹ là khác nhau, các cam kết ID phải khác nhau. Điều đó có nghĩa là khi so sánh các kho lưu trữ (như trong một lần đẩy hoặc kéo) khi Git tìm thấy một cam kết chung giữa hai kho lưu trữ, nó có thể ngừng kiểm tra. Điều này làm cho việc đẩy và kéo cực kỳ hiệu quả. Ví dụ ...

origin 
A - B - C - D - E [master] 

A - B [origin/master] 

Cuộc nói chuyện mạng cho git fetch origin đi một cái gì đó như thế này ...

  • local Hey nguồn gốc, những gì chi nhánh nào bạn có?
  • origin Tôi có bậc thầy tại E.
  • local Tôi không có E, tôi có chủ tại B.
  • origin B bạn nói? Tôi có B và đó là tổ tiên của E. Kiểm tra. Hãy để tôi gửi cho bạn C, D và E.

Đây cũng là lý do tại sao khi bạn viết lại cam kết rebase, mọi thứ sau khi thay đổi phải thay đổi. Đây là một ví dụ.

A - B - C - D - E - F - G [master] 

Giả sử bạn viết lại D, chỉ để thay đổi thông điệp tường trình một chút. Bây giờ D không còn có thể là D, nó phải được sao chép vào một cam kết mới, chúng ta sẽ gọi D1.

A - B - C - D - E - F - G [master] 
     \ 
      D1 

Trong khi D1 có thể có C như mẹ của nó (C không bị ảnh hưởng, cam kết không biết con cái của họ) nó bị ngắt kết nối từ E, F và G.Nếu chúng ta thay đổi cha mẹ của E thành D1, E không thể là E nữa. Nó phải được sao chép vào một commit mới E1.

A - B - C - D - E - F - G [master] 
     \ 
      D1 - E1 

Và cứ thế với F đến F1 và G đến G1.

A - B - C - D - E - F - G 
     \ 
      D1 - E1 - F1 - G1 [master] 

Tất cả đều có cùng mã, chỉ cha mẹ khác (hoặc trong trường hợp của D1, một thông báo cam kết khác).

11

Bạn có thể thấy chính xác những gì đi vào thực hiện một cam kết id bằng cách chạy

git cat-file commit HEAD 

Nó sẽ cung cấp cho bạn một cái gì đó giống như

tree 07e239f2f3d8adc12566eaf66e0ad670f36202b5 
parent 543a4849f7201da7bed297b279b7b1e9a086a255 
author Justin Howard <[email protected]> 1426631449 -0700 
committer Justin Howard <[email protected]> 1426631471 -0700 

My commit message 

Nó mang đến cho bạn:

  1. Một checksum của nội dung cây
  2. Id cam kết gốc (nếu đây là một hợp nhất, t ở đây sẽ có nhiều bậc phụ huynh)
  3. Tác giả của cam kết với timestamp
  4. Các committer của cam kết với timestamp
  5. Các cam kết thông báo

Git mất tất cả điều này và thực hiện một băm SHA1 của nó. Bạn có thể tái tạo các cam kết id bằng cách chạy

(printf "commit %s\0" $(git cat-file commit HEAD | wc -c); git cat-file commit HEAD) | sha1sum 

này bắt đầu ra bằng cách in các chuỗi commit theo sau là một không gian và số lượng byte của blob cat-file văn bản. Sau đó, thêm các đốm màu cat-file vào đó theo sau là một byte rỗng. Tất cả điều đó sau đó được chạy qua sha1sum.

Như bạn có thể thấy, không có gì xác định dự án hoặc kho lưu trữ trong thông tin này. Lý do mà điều này không gây ra vấn đề là bởi vì nó là không thiên văn cho hai hash cam kết khác nhau để va chạm.

+0

Điều này bổ sung thực sự tốt câu trả lời được lựa chọn, tôi đã kiểm tra nó, kịch bản shell thực sự hoạt động, tôi đoán điều này được sao chép từ mã thực tế, phải không? –

+1

@JeanVincent: Nó không được lấy chính xác từ mã. Tôi tưởng tượng nó được viết bằng C. Nhưng nó tái tạo chính xác thuật toán (hiện tại, nhưng những người đóng góp đang làm việc thay thế SHA1). –

+0

Đây có phải là nơi bạn có thông tin không? https://gist.github.com/masak/2415865 –