2010-11-02 37 views
37

這是關於git的內部結構。git使用什麼算法來檢測工作樹上的更改?

我一直在閱讀偉大的'Pro Git'書籍並瞭解git在內部如何工作(所有關於SHA1,blob,引用,tress,提交等等)。順便說一下,非常聰明的建築。

因此,爲了放入上下文,git將文件的內容作爲SHA1值引用,因此它能夠知道特定內容是否僅僅比較了散列值而發生了變化。但我的問題是關於git如何檢查工作樹中的內容是否已經改變。

天真的方法會認爲,每次運行命令git status或類似的命令時,它都將搜索工作目錄中的所有文件,計算SHA1並將其與具有上次提交的文件進行比較。但是對於大型項目來說,這看起來效率很低,就像Linux內核一樣。

另一個想法可能是檢查的最後修改日期的文件,但我認爲Git是不存儲該信息(當你克隆一個倉庫,所有的文件有一個新的時間)

我敢肯定,這以一種有效的方式做(git非常快),是否有人如何實現?

PD:只是爲了添加一個有趣的link關於git索引,特別指出索引保留有關文件時間戳的信息,即使樹對象不包含。

+1

請參閱:http://stackoverflow.com/questions/1778862/how-does-git-detect-a-file-modification – 2011-02-14 17:18:31

+0

[git如何檢測文件已被修改?](http:// stackoverflow .com/q/1778862/995714) – 2017-04-21 08:45:46

回答

26

Git的索引維護git最後一次將每個文件寫入工作樹的時間戳(並且每當文件從工作樹或提交中緩存時更新這些時間戳)。您可以通過git ls-files --debug查看元數據。除了時間戳之外,它還記錄來自lstat的大小,inode和其他信息,以減少誤報的可能性。

執行git-status時,它只是在工作樹中的每個文件上調用lstat並比較元數據以便快速確定哪些文件未更改。這在racy-gitupdate-index的文檔中有描述。

+1

剛纔我發現這個鏈接http://book.git-scm.com/7_the_git_index.html有一些額外的信息。謝謝! – Khelben 2010-11-02 07:30:06

7

在unix文件系統上,文件信息被跟蹤並且可以使用lstat方法進行接收。該stat structure包含多個時間戳,大小信息,以及更多:

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 */ 
}; 

看來,最初的Git簡單地依賴於這個stat structure來決定文件是否已經改變(see reference):

當檢查,如果它們不同,Git會先對這些文件運行lstat(2),並將結果與​​該信息

然而,競爭條件比較報告(racy-git),該發現如果一個文件被以下面的方式修改:

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

這左邊文件中被修改而不是由檢測LSTAT的狀態。

要解決這個問題,現在在這種情況下,lstat狀態不明確,Git會比較文件的內容以確定它是否已更改。


注:

如果有人被迷惑,就像我是約st_mtime description,其中指出,它被寫入更新「的大於零個字節,」這意味着絕對變化。

例如,在使用單個字符A一個文本文件,文件的情況下:如果A改爲B有0總字節數淨變化,但st_mtime仍會更新(有自己試試吧驗證,使用ls -l查看時間戳)。

相關問題