[英]Git not fetching ignored tracked files
這個問題幾乎與FAQ(關於如何阻止Git跟蹤被忽略的文件)相反。 在這種情況下, 我想跟蹤它們,而不是忽略它們。
我有一個.gitignore
文件,其中包含以下行:
**/*.exe
在大多數情況下, .exe
文件是構建的產物,並且將被忽略(此項目托管在MinGW和Cygwin的組合上,因此二進制文件在Windows上運行。)
但是,此忽略規則也有例外。 我已經在源代碼樹中添加了一些.exe
文件。 據我了解, .gitignore
不適用於跟蹤的文件(索引中的文件)。
但是,當我克隆我的存儲庫時,不會提取.exe
文件。
如果我在添加了原始存儲庫的文件中對該文件執行git status
, 則會得到:
$ git status program.exe On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working tree clean
該文件也存在於工作樹中:
$ ls -l program.exe -rwxrwx---+ 1 abc xyz 23040 Mar 20 15:35 program.exe
$ git log program.exe
commit 412fd58b5a11bf6a40f661109e71f2c0026c1643 Author: abc <abc@xyz.com> Date: Sat Apr 1 02:21:40 2017 -0700
cleanup
commit b0a2efd4dc17b70d046c1e7d78e3142cf29410ba Author: abc <abc@xyz.com> Date: Mon Mar 20 18:41:00 2017 -0700
Initial version
我已將提交推送到另一台服務器上的裸存儲庫中。 我可以在裸倉庫中找到與最新簽入相對應的blob:
MyProject.git/objects/41/2fd58b5a11bf6a40f661109e71f2c0026c1643
因此很明顯,它正在被跟蹤。 但是,當我克隆存儲庫時,它不會出現在工作樹中。 在克隆的存儲庫上 :
$ git status program.exe On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working tree clean
$ ls -l program.exe ls: cannot access 'program.exe': No such file or directory
我沒有使用assume-unchanged
的東西。
在其他存儲庫中提取時,是否被忽略但跟蹤的文件仍然被忽略?
即使它們匹配.gitignore
您如何強制它們被獲取?
您是否需要從匹配的.gitignore
中排除它們才能獲取它們?
$ git --version git version 2.12.0.windows.1
編輯:記住,將跟蹤文件添加到.gitignore
之后,我不是想忽略它們; 我正在嘗試獲取跟蹤和提交的文件,盡管它們匹配.gitignore
。
在最初的答案和下面的大量討論之間,我意識到我認為不是很明顯的事情。 當我第一次使用Git時,這當然對我來說並不明顯(可能長達數月甚至數年)。 這里有兩個部分:
在Git中, tracked表示索引 。
但是,每次簽出某些特定的提交(例如git checkout otherbranch
,索引(您將進行的下一次提交)都會更改 。
這意味着是否跟蹤文件是相對的,而不是絕對的。 可以在git checkout branch1
之后跟蹤文件F ,然后在git checkout branch2
之后取消跟蹤文件F。 它可能在分支master
上的先前提交中已被跟蹤,而現在在分支master
上未被跟蹤。 如果該文件是既未經跟蹤和忽略,但在過去被跟蹤和目前在工作樹,它可以是相當難以弄清楚發生了什么事情。 該文件即使在歷史記錄中也不會出現在新的克隆中。
(原始,請在此處填寫完整的答案。)
但是,當我克隆我的存儲庫時,不會提取
.exe
文件。
git clone
操作不會獲取任何文件。 相反,它將獲取提交。 現在,提交包含文件確實是事實,所以這看起來似乎毫無意義,但它對於您的問題(實際上對幾乎所有Git都至關重要)至關重要,因此確實很重要。 Git不在乎文件; Git就是關於提交的。
提交本身形成了歷史。 每個提交都包含一些文件集,但是還具有指向先前提交的后向指針:“這就是我們現在擁有的。這是我們之前提交的哈希ID。” 我們稱其為提交的父級 。 該父提交也有其自己的父。 該向后鏈是存儲庫中的歷史記錄。
像master
這樣的分支名稱是Git記錄該分支的當前哈希ID的方式。 Git在最近一次提交時從此處開始,使用分支名稱; 然后,如果需要,Git會向后工作,獲取較早的(父)提交,並按要求轉到較舊的(祖父母,曾祖父母等)提交。
運行git clone
復制分支名稱,分支提交,該提交的父級以及父級的父級,依此類推; 這樣您就可以獲取所有歷史記錄。 每個提交都帶有與該提交一起存儲的文件,因此一旦擁有所有提交,就不僅擁有所有當前文件,而且還擁有所有先前的當前父提交文件,以及所有早先的文件。到第一次提交。 但是所有這些文件都以僅Git的秘密格式隱藏起來,除了Git以外對其他任何東西都沒有好處。 仍然是git clone
復制的內容。
當然,為了使Git實際有用,我們需要使用一些實際有用的形式的文件。 因此,Git在此提交歷史記錄中添加了一些內容,但這並不是被克隆的內容。 這就是您的問題所在。
在一個有用的(即非--bare
)存儲庫中,我們不僅需要所有提交和各種分支名稱來記住其最近的哈希ID,還需要一個工作樹 。 工作樹是我們可以處理實際文件的地方。 這些文件以樹狀結構排列,其中包含頂級文件和目錄,並根據需要在目錄中包含更多文件和子目錄。 (因此,名稱為“工作樹”:這是工作表單文件的樹。)
Git還會拋出Git稱為索引的另一件事。 索引的簡短描述是它是您構建下一個提交的地方。 如果您從不對自己的存儲庫進行任何更改,則該索引會為您帶來麻煩,但是Git仍然會迫使您了解它。 如果你做的修改,該指數是至關重要的,因為進行更改的方法是修改在工作樹的事情,然后使用git add
到這些修改復制回索引,使他們上演 ,明年提交。 然后,當您運行git commit
進行新提交時,Git 現在將索引中的內容(即以前存在的所有舊內容,除了您用git add
新內容替換的內容)復制到新提交中。
要知道這一點確實非常重要: 索引會跟蹤工作樹中的內容。 實際上,這就是“被跟蹤”的含義:被跟蹤 在索引中的含義。 但是索引也是下一次提交中的索引,因此它開始與當前提交中的匹配。
您可以(通常這樣做 )在工作樹中包含故意未被跟蹤的文件。 例如,您的*.exe
文件被無意跟蹤。 未被跟蹤意味着它們不在索引中。 這意味着它們也不在當前提交中, 1 ,現在我們可以看到會有問題。
1也就是說, 除非索引為“ dirty”, 否則它們不在當前提交中,因此需要將其寫出到新提交中。 再次,這是您首先進行新提交的方式:您修改工作樹中的內容,例如修改文件,添加全新文件或刪除現有文件,然后復制這些“臟”的工作,樹文件進入索引,“使索引變臟”。 然后,您使用git commit
進行新的提交。 新提交的父級是當前提交的父級,而其文件就是索引中的內容。 然后,Git將新提交的哈希ID寫入分支名稱,並且新提交現在是歷史記錄的一部分,將被永久保存。
您提到:
我可以在裸倉庫中找到與最新簽入相對應的blob:
MyProject.git/objects/41/2fd58b5a11bf6a40f661109e71f2c0026c1643
這意味着該文件在某些時候提交。 這是歷史的承諾。 這並不意味着該文件位於像master
這樣的分支上的最新提交中。 該存儲庫具有僅Git內部(壓縮對象)格式,曾經提交過的每個文件的每個版本。 並且,您可以而且經常在工作樹中擁有不在索引中且不在當前提交中的文件。 該文件很可能與您過去提交的文件匹配。
因此,文件在存儲庫中的存在並不意味着它在某個特定分支上的最新提交中 。 這確實意味着您可以提取歷史文件。 例如,鑒於以上所述,您可以:
git show 412fd58b5a11bf6a40f661109e71f2c0026c1643 > foo.exe
隨時將其提取到foo.exe
。 如果您知道提交哈希和路徑,則也可以使用它:
git show 1234567:path/to/foo.exe > foo.exe
以及提交是否具有名稱 (例如分支或標記名稱):
git show name:path/to/foo.exe > foo.exe
您可以使用此方法提取歷史文件,但是顯然有些痛苦。
git clone
在獲取所有提交后會做什么 如前所述, git clone
首先復制提交和分支名稱。 實際上,默認情況下,它將這些分支名稱重命名為Git所謂的“遠程跟蹤分支”。 但是,在退出它並調用一切正常且准備就緒之前的最后一步, git clone
填充了您的工作樹 。
它在你的工作樹填充的方法是git checkout
一些分行的名稱,通常是master
。 該分支名稱會記住該分支的最新提交的哈希ID。 該提交是從索引進行的,並且該索引中沒有.exe
文件。 因此,最新的master
提交中沒有.exe
文件。
由於此工作樹是全新的,並且檢出的提交中沒有.exe
文件,因此新工作樹中也沒有.exe
文件。 這就是為什么他們失蹤的原因。
如果這些.exe
文件確實存在於存儲庫中的其他提交中,則它們位於存儲庫中,您可以將其取出。 您只是沒有簡單地將它們弄出來:
git checkout master
因為這只會將為master
上的最新提交保存的文件提取到索引中,然后提取到工作樹中。
.exe
文件? 好吧,這部分取決於您。 Git在這里沒有為您提供預包裝的解決方案。 它們可能位於您要克隆的另一個Git存儲庫的工作樹中,但是克隆協議中沒有任何內容可以采用另一個Git的工作樹 。
處理這個的一個方法是有一個承諾,它包含什么,但最新.exe
文件。 然后您可以告訴Git:
feede3e
所有文件提取到我的工作樹中,而不提取到索引中
例如,假設該提交具有該哈希ID。 事實證明,這非常困難,因為Git 確實想將提交中的文件提取到索引中,然后再將它們復制到工作樹中。 將它們放入索引會使它們被跟蹤 ,這不是您想要的。 當然,首先要將那些.exe
文件提交到提交中,那么,還有什么呢:等待它……您猜對了嗎? 是的,這需要將那些.exe
文件放入索引中!
Git不會讓您同時擁有它。 要么跟蹤文件,要么它們都在索引中,所以它們確實進入了提交; 否則它們將無法跟蹤,因此它們不在索引中,因此它們不會進入提交。 選擇一個並堅持下去。 如果你喜歡,使用git worktree add
,或者這個倉庫,或者完全獨立的存儲設備的單獨的克隆,創建使用不同的分支, 確實有第二個庫或worktree .exe
跟蹤和提交的文件。 實際上,您可能希望此分支或其他存儲庫僅跟蹤和保存.exe
文件。 然后,您可以從那里簡單地復制.exe
文件。
或者,當然,您可以從確實有它們的地方獲得它們,但是可以使用git clone
其他方法。
(它實際上是有可能做到這一切,沒有一個單獨的工作樹,使用各種Git的管道命令和臨時索引的,但它是相當棘手的,而不是Git的是如何構建的工作。在任何情況下,請注意,你會希望有一個名稱(例如分支名稱),您可以輕松記住,以獲取具有最新 .exe
文件的最新提交;具有分支名稱的想法可以為您記住哈希ID,提交對象可以保存文件,還可以記得上一次提交的對象...好,這是一個分支 ,是混帳做什么:它使能記住承諾,能記住已保存列的索引文件的哈希分支的名稱,以便你真的想要一個獨立的工作樹和獨立。索引,用於更新和提交文件。畢竟,您真的不想在Git模型之外工作。)
.gitignore
文件是一個紅色鯡魚 .gitignore
中的條目所做的主要兩件事:
它可以抑制有關未跟蹤文件的投訴 。 如果foo.exe
存在於工作樹中但不存在於索引中,因此不會保存在下一個git commit
,那么Git 會對您發牢騷 。 它不斷地告訴您:“嘿, foo.exe
不會被提交!記住將foo.exe
添加到索引中!不要忘記foo.exe
,否則它將不會被提交!” 這得到討厭,和你想看到的,你真的忘記文件投訴的方式獲得。 因此,將foo.exe
或*.exe
添加到.gitignore
關閉此投訴。
它禁止foo.exe
或git add -a
自動添加。 您可以通過提及目錄名稱或使用--all
或使用git add *
類的shell全局功能,整體上添加骯臟的工作樹文件,而不必一次手動git add
向索引中git add
一個文件。 如果foo.exe
當前未被跟蹤並且在.gitignore
列出,則它們實際上不會將foo.exe
復制到索引中。 甚至git add *
都會跳過它,並有抱怨; git add .
或git add -a
會跳過它而不會產生任何投訴。
請注意,如果跟蹤文件, 則在.gitignore
中列出文件名無效。 .gitignore
中的條目主要是關於防止文件被跟蹤,而不是停止已經生效的任何操作。
您的構建文件位於bin文件夾中。 因此您必須將.gitignore添加到:
bin/*.exe or bin/*
並且您應該從gitignore文件中刪除此行:
**/*.exe
編輯:如果要忽略除某些文件以外的所有exe文件,可以使用“!”將其排除。 在行模式的開頭,請查看此https://stackoverflow.com/a/987162/5410373
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.