Git thực sự đang làm gì khi nó nói rằng đó là giải quyết deltas phạm?


187

Trong bản sao đầu tiên của kho lưu trữ, git trước tiên nhận các đối tượng (đủ rõ ràng), sau đó dành khoảng thời gian tương tự để "giải quyết deltas". Điều gì thực sự xảy ra trong giai đoạn này của bản sao?



1
Xem thêm, đối với Git 2.20 (Q4 2018) và các đảo châu thổ khác: stackoverflow.com/a/52458712/6309
VonC

Câu trả lời:


54

Git sử dụng mã hóa delta để lưu trữ một số đối tượng trong packfiles. Tuy nhiên, bạn không muốn phải phát lại mọi thay đổi từng có trên một tệp đã cho để có phiên bản hiện tại, do đó, Git cũng thỉnh thoảng có ảnh chụp nhanh nội dung tệp được lưu trữ. "Giải quyết đồng bằng" là bước liên quan đến việc đảm bảo tất cả những điều đó vẫn nhất quán.

Đây là một chương trong phần "Git Internals" của cuốn sách Pro Git, có sẵn trực tuyến, nói về điều này.


80
Câu trả lời này không chính xác. Nó dường như mô tả cách Mercurial hoạt động, không phải Git. Nó đang xuất hiện trong các tìm kiếm của Google về vấn đề này vì vậy tôi cảm thấy cần phải trả lời. Git không lưu trữ sự khác biệt giữa các cam kết như deltas; Git là một cửa hàng "toàn bộ đối tượng". Như vậy, Git không cần "ảnh chụp nhanh" để hiển thị bất kỳ tệp đã cho nào vì lịch sử tệp không cần phải được xây dựng lại từ deltas. Đó là cách Mercurial hoạt động.
nexus nói

12
Nơi duy nhất mà mã hóa delta xuất hiện là trong tệp pack hoàn toàn dành cho nén và chuyển - nó không thay đổi cách Git "nhìn" thế giới. ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/ mẹo ) Vui lòng xem câu trả lời của araqnid bên dưới để có câu trả lời chính xác.
nexus nói

4
Tất cả "ảnh chụp nhanh" có nghĩa là trong ngữ cảnh này là bản sao đầy đủ của trạng thái tệp, thay vì phiên bản được mã hóa delta. Như bạn đã đề cập, Git không sử dụng mã hóa delta trong packfiles. Không ai nói rằng nó "thay đổi cách Git nhìn thế giới"; xin vui lòng ngừng dự đoán giả định của riêng bạn.
Amber

2
Câu trả lời của bạn vẫn không chính xác. "Git cũng thỉnh thoảng có ảnh chụp nhanh nội dung tệp được lưu trữ." -- đó là không đúng. "'Giải quyết đồng bằng' là bước liên quan đến việc đảm bảo tất cả những điều đó vẫn nhất quán." - điều đó cũng không đúng, phản hồi của araqnid dưới đây là chính xác.
nexus nói

1
Như được mô tả trong chương được đề cập ở trên, Git luôn lưu trữ toàn bộ nội dung tệp của phiên bản mới nhất. Các phiên bản trước được lưu trữ dưới dạng tệp mã hóa delta khi chúng là tệp "lỏng lẻo". Định kỳ (bằng cách gọi git gchoặc bất cứ khi nào Git xác định cần thiết) Git sẽ nén tất cả các tệp "lỏng" vào một gói để tiết kiệm dung lượng và một tệp chỉ mục vào gói đó sẽ được tạo. Vì vậy, zlib sẽ nén bằng thuật toán delta của riêng mình nhưng Git không sử dụng mã hóa delta để lưu trữ các phiên bản trước. Vì truy cập phổ biến và thường xuyên nhất là phiên bản mới nhất, được lưu trữ dưới dạng ảnh chụp nhanh.
BrionS

118

Các giai đoạn git clonelà:

  1. Nhận tệp "gói" của tất cả các đối tượng trong cơ sở dữ liệu repo
  2. Tạo một tệp chỉ mục cho gói nhận được
  3. Kiểm tra sửa đổi đầu (rõ ràng cho một repo không trần)

"Giải quyết deltas" là thông báo được hiển thị cho giai đoạn thứ hai, lập chỉ mục tệp gói ("git index-pack").

Các tệp gói không có ID đối tượng thực tế trong đó, chỉ có nội dung đối tượng. Vì vậy, để xác định ID đối tượng là gì, git phải thực hiện giải nén + SHA1 của từng đối tượng trong gói để tạo ID đối tượng, sau đó được ghi vào tệp chỉ mục.

Một đối tượng trong tệp gói có thể được lưu trữ dưới dạng delta tức là một chuỗi các thay đổi để thực hiện đối với một số đối tượng khác. Trong trường hợp này, git cần truy xuất đối tượng cơ sở, áp dụng các lệnh và SHA1 kết quả. Bản thân đối tượng cơ sở có thể phải được bắt nguồn bằng cách áp dụng một chuỗi các lệnh delta. (Mặc dù trong trường hợp nhân bản, đối tượng cơ sở sẽ đã gặp phải, nhưng có giới hạn đối với số lượng đối tượng được sản xuất được lưu trong bộ nhớ).

Tóm lại, giai đoạn "giải quyết deltas" liên quan đến việc giải nén và kiểm tra toàn bộ cơ sở dữ liệu repo, điều này không gây ngạc nhiên khi mất khá nhiều thời gian. Có lẽ việc giải nén và tính toán SHA1 thực sự tốn nhiều thời gian hơn so với việc áp dụng các lệnh delta.

Trong trường hợp tìm nạp tiếp theo, tệp gói nhận được có thể chứa các tham chiếu (dưới dạng cơ sở đối tượng delta) đến các đối tượng khác mà git nhận được dự kiến ​​sẽ có. Trong trường hợp này, git nhận thực sự viết lại tệp gói đã nhận để bao gồm mọi đối tượng được tham chiếu như vậy, sao cho mọi tệp gói được lưu trữ là tự cung cấp. Đây có thể là nơi thông điệp "giải quyết deltas" bắt nguồn.


7
Điều này có thể được song song?
brooksbp

Là nén delta này hơn là lưu trữ nhiều đối tượng trong một luồng dữ liệu zlib?
fuz

1
@FUZxxl vâng, nó sử dụng một thuật toán như diff hoặc xdelta để so sánh hai đốm màu và tạo ra một kịch bản chỉnh sửa
araqnid

@brooksbp: Chỉ với những hạn chế. Bởi vì đối tượng có id 103fa49 có thể cần giải mã df85b51, nhưng khi bạn nhận được 103fa49, df85b51 vẫn chưa có (các tệp gói được sắp xếp nghiêm ngặt bởi băm sha1). Vì vậy, đối với mọi thứ chỉ tham khảo những thứ đã có, mọi thứ đều dễ dàng, nhưng đối với mọi thứ khác, bạn sẽ phải đợi cho đến khi nhận được. Và nén delta này có thể được lồng nhau, vì vậy 103fa49 có thể cần 4e9ba42, đến lượt nó cần 29ad945, đến lượt nó cần c9e645a ... bạn có được hình ảnh. [vâng, tôi nhận thấy đã được 4 năm;)]
Bodo Thiesen

2
@brooksbp: Hóa ra, tôi đã nhầm, tập tin gói KHÔNG cần phải được sắp xếp theo băm sha1. Ngoài ra, khi viết, git viết các đối tượng cần thiết trước các đối tượng cần chúng. Vì vậy, thực sự bạn sẽ có thể song song nó. Chỉ có nhược điểm còn tồn tại: Bởi vì bạn không biết bạn sẽ cần những đối tượng nào sau này, bạn sẽ phải tạo lại nhiều lần. Xem tại đây: kernel.org/pub/software/scm/git/docs/technical/iêu
Bodo Thiesen

4

Amber dường như đang mô tả mô hình đối tượng mà Mercurial hoặc sử dụng tương tự. Git không lưu trữ đồng bằng giữa các phiên bản tiếp theo của một đối tượng, mà là các ảnh chụp nhanh đầy đủ của đối tượng, mọi lúc. Sau đó, nó nén các ảnh chụp nhanh này bằng cách sử dụng nén delta, cố gắng tìm các đồng bằng tốt để sử dụng, bất kể chúng tồn tại ở đâu trong lịch sử.


5
Trên thực tế, trong khi Git có thể lưu trữ các đối tượng lỏng lẻo, chúng không nhất thiết phải luôn được lưu trữ như vậy - vì các đối tượng lỏng lẻo có thể bị xóa và thay thế bằng nội dung đóng gói. Tôi không nghĩ câu trả lời của Amber nói bất cứ điều gì về các phiên bản tiếp theo.
AlBlue
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.