Mặc dù thực tế là GIT KHÔNG lưu trữ deltas tệp, bạn vẫn có thể quay lại các phiên bản tệp trước đó (không giới hạn thời gian?)


14

Tôi đã đọc rằng Git không lưu trữ tập tin deltas. Nếu điều này là đúng, làm thế nào để nó hỗ trợ khôi phục tập tin cho các phiên bản trước? Nếu nó lưu trữ toàn bộ tệp, không gian lưu trữ trên đĩa phải lớn lên không thể quản lý được. Git có hỗ trợ rollback tệp và diff (s) trở lại tệp phiên bản 1 không? Nó thậm chí còn hỗ trợ một khái niệm phiên bản có liên quan đến các tập tin? Đây là (tôi tin) cần thiết cho sự hiểu biết của tôi về một VCS / DVCS và nhu cầu của tôi. Tôi cần có thể so sánh những gì tôi sắp kiểm tra với các phiên bản trước.

Câu trả lời:


44

Git không tự mình vứt bỏ thông tin *. Tất cả các phiên bản trước của mỗi tệp luôn có sẵn để hoàn nguyên, tìm khác biệt, kiểm tra, et cetera.

Toàn cây so với tập tin cá nhân

Những gì bạn có thể đang cố gắng hòa giải là ý tưởng truy cập một phiên bản cũ của một tệp riêng lẻ so với thực tế là mô hình lịch sử của Git tập trung vào toàn bộ cây. Phiên bản toàn cây đòi hỏi phải có thêm một chút công việc để xem (ví dụ) phiên bản foo.cnhư đã tồn tại mười foo.clần trước đây so với mười thay đổi toàn cây trước đây:

# 10 foo.c-changes ago
git show $(git rev-list -n 10 --reverse HEAD -- foo.c | head -1):foo.c

# 10 whole-tree-changes ago
git show HEAD~10:foo.c

Lợi ích của việc định hướng cây, chủ yếu là khả năng xem các cam kết như là một đơn vị thay đổi phụ thuộc lẫn nhau được thực hiện cho các phần khác nhau của toàn bộ cây, nói chung vượt trội hơn nhiều so với việc gõ thêm (có thể giảm bớt bằng bí danh, tập lệnh, et cetera) và thời gian CPU đã dành đào qua các cam kết trong quá khứ.

Hiệu quả lưu trữ

Khi một đối tượng mới (ví dụ: một tệp có nội dung chưa từng thấy trước đó) xâm nhập vào hệ thống, nó sẽ được lưu trữ với nén (zlib) đơn giản dưới dạng một đối tượng lỏng lẻo. Khi tích lũy đủ các đối tượng lỏng lẻo (dựa trên gc.autotùy chọn cấu hình; hoặc khi người dùng chạy git gc hoặc một trong các lệnh đóng gói cấp thấp hơn), Git sẽ thu thập nhiều đối tượng lỏng lẻo vào một tập tin gói khác.

Các đối tượng trong tệp gói có thể được lưu trữ dưới dạng dữ liệu nén đơn giản (giống như một đối tượng lỏng lẻo, chỉ được gói cùng với các đối tượng khác) hoặc dưới dạng deltas nén đối với một số đối tượng khác. Deltas có thể được nối với nhau đến độ sâu có thể định cấu hình ( pack.depth) và có thể được tạo ra để chống lại bất kỳ đối tượng phù hợp nào ( pack.windowkiểm soát mức độ tìm kiếm Git rộng rãi cho cơ sở delta tốt nhất; một phiên bản của tệp không liên quan trong lịch sử có thể được sử dụng làm cơ sở nén delta tốt). Các vĩ độ mà cấu hình độ sâu và kích thước cửa sổ cung cấp cho công cụ nén delta thường dẫn đến nén delta tốt hơn so với nén nén phiên bản đơn giản theo kiểu CVS đơn giản so với phiên bản trước.

Chính việc nén delta tích cực này (kết hợp với nén zlib bình thường) thường có thể để kho lưu trữ Git (có lịch sử đầy đủ và cây làm việc không nén) chiếm ít không gian hơn so với kiểm tra SVN duy nhất (với cây làm việc không nén và bản sao nguyên sơ).

Xem phần Git lưu trữ các đối tượng và các phần Packfile của Sách cộng đồng Git . Ngoài ra git gói-đối tượng manpage .

* Bạn có thể nói Git vứt bỏ các cam kết bằng cách viết lại lịch sử, và với các lệnh như git reset , nhưng ngay cả trong những trường hợp này, Git đã bị treo lên trên các cam kết mới bị loại bỏ trong một thời gian, chỉ trong trường hợp bạn quyết định rằng bạn cần chúng. Xem git refloggit prune .


3
+1 chỉ cho số lượng và chi tiết của thông tin bạn cung cấp.
Tamara Wijsman

3
Ngoài ra, vì Git sử dụng ảnh chụp nhanh của các tệp chứ không phải deltas, nên việc quay lại một chặng đường dài trong lịch sử thực sự dễ dàng hơn. Hãy tưởng tượng bạn cần xem một tập tin từ 20 lần xác nhận trước. Với deltas, bạn cần hoàn tác 20 thay đổi; với ảnh chụp nhanh, bạn chỉ cần chụp đúng ảnh chụp. Lịch sử của bạn càng dài, lợi thế càng lớn. Và nếu bạn muốn thấy sự khác biệt giữa phiên bản hiện tại và phiên bản hiện tại, thì đó chỉ là một khác biệt duy nhất, thay vì phải quyết định những gì đã được thực hiện, hoàn tác, làm lại, v.v.
Nathan Long

Chris, bạn dường như có một xử lý khá tốt trên nội bộ Git. Bất cứ cơ hội nào bạn có thể có một cú swing lúc này? stackoverflow.com/questions/5176225/ trộm
Nathan Long

@ChrisJohnsen Xin hãy giúp tôi hiểu điều này. Dựa trên những gì bạn đã nói, Git có thể có được hiệu quả lưu trữ tương tự (hoặc tốt hơn) so với Subversion không? Tôi biết rằng nếu tôi cam kết một tệp có ít thay đổi nhiều lần, dữ liệu trị giá 1GB có thể được lưu trong 100MB. Git có thể làm như vậy không?
Alireza Noori

@AlirezaNoori: Tất cả phụ thuộc vào bản chất của dữ liệu và các thay đổi được ghi lại (kích thước của tệp, độ nén của tệp, kích thước và vị trí của các thay đổi, v.v.). Một cái gì đó như thế chắc chắn là có thể (tùy thuộc vào chi tiết cụ thể). Nói chung, các tệp gói của Git có thể rút ra từ một lựa chọn cơ sở lớn hơn cho nén delta của nó so với các đồng bằng thời gian đảo ngược hoàn toàn mà các máy chủ SVN sử dụng (được sử dụng? Tôi không theo dõi phát triển SVN). Nếu bạn có một số câu hỏi cụ thể trong đầu, bạn nên xem xét việc hỏi một câu hỏi mới bao gồm tất cả các chi tiết thích hợp.
Chris Johnsen

1

Nó có thể được đọc trên cùng một trang:

...

Do đó, Git không ghi lại rõ ràng mối quan hệ sửa đổi tệp ở bất kỳ cấp nào bên dưới cây mã nguồn.

...

Nó đắt hơn một chút để kiểm tra lịch sử thay đổi của một tệp so với toàn bộ dự án. Để có được lịch sử thay đổi ảnh hưởng đến một tệp nhất định, Git phải đi theo lịch sử toàn cầu và sau đó xác định xem mỗi thay đổi có sửa đổi tệp đó không. Tuy nhiên, phương pháp kiểm tra lịch sử này cho phép Git tạo ra với hiệu quả tương đương một lịch sử duy nhất hiển thị các thay đổi đối với một tập hợp các tệp tùy ý. Ví dụ, thư mục con của cây nguồn cộng với tệp tiêu đề toàn cầu được liên kết là một trường hợp rất phổ biến.

...

Do đó, bạn có thể quay lại các phiên bản trước của một tệp và so sánh hai tệp.


1

Trên thực tế, git lưu deltas của các tệp, nhưng nó lưu chúng dưới dạng delta của toàn bộ cây tệp.

Để xem sự khác biệt giữa các phiên bản, hãy thực hiện một trong các thao tác sau:

  1. git diff - cho thấy sự khác biệt giữa lần kiểm tra cuối cùng trong phiên bản và các tệp đã được thay đổi, nhưng không git addchạy trên chúng.
  2. git diff --cached - cho thấy sự khác biệt giữa phiên bản trước và những gì tất cả các tệp đã git addchạy, nhưng chưa được cam kết
  3. git diff commitid - hiển thị sự khác biệt giữa thư mục làm việc hiện tại và một cam kết trước đó như được chỉ định với cam kết
  4. git diff commita..commitb - cho thấy sự khác biệt giữa hai cam kết, a và b. Các cam kết cũng có thể là tên tượng trưng như các nhánh hoặc thẻ.

Câu trả lời này không thực sự chính xác. Tất cả các lệnh đó có thể được áp dụng cho một tập hợp các tệp tùy ý cũng như toàn bộ cây - chỉ cần thêm tên tệp vào cuối ...
naught101
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.