2010-11-02 27 views
37

Đây là về nội bộ của git.Thuật toán nào git sử dụng để phát hiện các thay đổi trên cây làm việc của bạn?

Tôi đã đọc cuốn sách tuyệt vời 'Pro Git' và tìm hiểu một chút về cách git hoạt động trong nội bộ (tất cả về SHA1, blobs, tài liệu tham khảo, tress, cam kết, v.v.). Kiến trúc khá thông minh, nhân tiện. Vì vậy, để đưa vào ngữ cảnh, git tham chiếu nội dung của một tệp dưới dạng giá trị SHA1, do đó, nó có thể biết liệu nội dung cụ thể có thay đổi hay không chỉ so sánh giá trị băm. Nhưng câu hỏi của tôi là cụ thể về cách git kiểm tra nội dung trong cây đang thay đổi hay không.

Cách tiếp cận ngây thơ sẽ nghĩ rằng, mỗi lần bạn chạy lệnh là git status hoặc lệnh tương tự, nó sẽ tìm kiếm tất cả các tệp trên thư mục làm việc, tính toán SHA1 và so sánh nó với một . Nhưng điều đó có vẻ rất không hiệu quả đối với các dự án lớn, như hạt nhân Linux.

ý tưởng khác có thể là để kiểm tra ngày sửa đổi cuối cùng trên tập tin, nhưng tôi nghĩ rằng git không lưu trữ thông tin (khi bạn sao chép một kho lưu trữ, tất cả các file có một thời gian mới)

tôi chắc chắn rằng đó là thực hiện nó một cách hiệu quả (git thực sự nhanh), có ai đạt được điều đó không?

PD: Chỉ cần thêm một số thú vị link về chỉ mục git, cụ thể là chỉ mục giữ thông tin về tệp thời gian, ngay cả khi đối tượng cây không.

+1

Xem: http://stackoverflow.com/questions/1778862/how-does-git-detect-a-file-modification –

+0

[Làm cách nào để git phát hiện thấy tệp đã bị sửa đổi?] (Http: // stackoverflow .com/q/1778862/995714) –

Trả lời

26

Chỉ mục của Git duy trì dấu thời gian khi git viết lần cuối mỗi tệp vào cây đang hoạt động (và cập nhật các tệp này bất cứ khi nào tệp được lưu trong bộ nhớ cache từ cây đang hoạt động hoặc từ cam kết). Bạn có thể xem siêu dữ liệu với git ls-files --debug. Ngoài dấu thời gian, nó ghi lại kích thước, inode và các thông tin khác từ lstat để giảm nguy cơ dương tính giả.

Khi bạn thực hiện trạng thái git, nó chỉ cần gọi lstat trên mọi tệp trong cây đang hoạt động và so sánh siêu dữ liệu để nhanh chóng xác định tệp nào không thay đổi. Điều này được mô tả trong tài liệu theo racy-gitupdate-index.

+1

Vừa mới tìm thấy liên kết này http://book.git-scm.com/7_the_git_index.html với một số thông tin bổ sung. Cảm ơn! – Khelben

7

Trên hệ thống tệp unix, thông tin tệp được theo dõi và có thể được truy cập bằng phương thức lstat. Các stat structure chứa nhiều thời gian tem, thông tin kích thước, và nhiều hơn nữa:

struct stat { 
    dev_t  st_dev;  /* ID of device containing file */ 
    ino_t  st_ino;  /* inode number */ 
    mode_t st_mode; /* protection */ 
    nlink_t st_nlink; /* number of hard links */ 
    uid_t  st_uid;  /* user ID of owner */ 
    gid_t  st_gid;  /* group ID of owner */ 
    dev_t  st_rdev; /* device ID (if special file) */ 
    off_t  st_size; /* total size, in bytes */ 
    blksize_t st_blksize; /* blocksize for file system I/O */ 
    blkcnt_t st_blocks; /* number of 512B blocks allocated */ 
    time_t st_atime; /* time of last access */ 
    time_t st_mtime; /* time of last modification */ 
    time_t st_ctime; /* time of last status change */ 
}; 

Dường như ban đầu Git chỉ đơn giản dựa vào stat structure này để quyết định nếu một tập tin đã được thay đổi (see reference):

Khi kiểm tra xem chúng có khác nhau hay không, Git chạy trước tiên lstat(2) trên các tệp và so sánh kết quả với thông tin này

Tuy nhiên, điều kiện chủng tộc đã được báo cáo ()) được tìm thấy nếu một tập tin đã được sửa đổi theo cách sau đây:

: modify 'foo' 
$ git update-index 'foo' 
: modify 'foo' again, in-place, without changing its size 
         (And quickly enough to not change it's timestamps) 

này rời khỏi tập tin trong một trạng thái đó đã được sửa đổi nhưng không thể phát hiện được bởi lstat.

Để khắc phục sự cố này, hiện tại trong trường hợp tình trạng lstat không rõ ràng, Git so sánh nội dung của tệp để xác định xem nó có bị thay đổi không.


LƯU Ý:

Nếu bất cứ ai đang bối rối, như tôi đã, khoảng st_mtime description, trong đó nêu rằng nó được cập nhật bởi viết "hơn zero byte," điều này có nghĩa tuyệt đối thay đổi. Ví dụ: trong trường hợp tệp tệp văn bản có một ký tự A: nếu A được đổi thành B có 0 thay đổi ròng về tổng kích thước byte, nhưng st_mtime sẽ vẫn được cập nhật (phải tự mình thử nghiệm) để xác minh, hãy sử dụng ls -l để xem dấu thời gian).

Các vấn đề liên quan