[英]Undo git update-index --no-assume-unchanged (not working) and be able to see these local changes again
更新:我的權限問題以某種方式任意修復了,因為現在完全相同的遠程分支create命令可以工作了,因此(您可能猜到了)這不是由此跟蹤問題引起的。
現在,我只是想解決跟蹤問題。 謝謝!
原始語言:我最初在多個文件中應用了以下內容:
git update-index --assume-unchanged filename.py
參考此文檔:
https://git-scm.com/docs/git-update-index#_using_assume_unchanged_bit
隱藏工作目錄更改中的某些文件(將文件添加到.git/info/exclude
似乎沒有效果-盡管路徑正確且尚未提交,但文件仍然可見)。
然后,我遇到了一些問題,這些問題推到了以前從未出現過的遠程分支,標准
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
因此,考慮到在運行update-index
之前我沒有訪問問題,我決定恢復該--assume-unchanged
因為我沒有對git repo進行任何其他操作。
我能夠使用查看這些assume-unchanged
文件
git ls-files -v | grep '^[a-z]'
我試圖通過使用以下方式恢復assume-unchanged
git update-index --really-refresh
如此處有關在多個文件中還原assume-unchanged
指示:
這沒有還原它們,然后我嘗試了
git ls-files -v | grep '^[a-z]' | cut -c 3- | tr '\012' '\000' | xargs -0 git update-index --no-assume-unchanged
根據此建議:
這些文件仍然不可見,我現在也不再能夠通過運行來查看它們
git ls-files -v | grep '^[a-z]'
我還嘗試在我的一個文件中嘗試了此操作:
git update-index --skip-worktree file.py
按照這里
https://git-scm.com/docs/git-update-index#_skip_worktree_bit
據我所知, skip-worktree
於assume-unchanged
因此我希望看到該文件的某些狀態更改。 依然沒有。
如何將文件恢復為可見並在工作目錄中跟蹤更改?
還有一個問題是,這可能會影響我創建新的遠程分支機構的訪問權限嗎?
您在這里有兩個不同的問題。 您的fatal: Could not read from remote repository
錯誤fatal: Could not read from remote repository
錯誤完全獨立於您在索引中設置或清除的任何標志位。 它暗示着:
http
, https
, ssh://
或git://
)的任何協議,到另一個Git的連接失敗,或者 如果連接本身失敗,通常您應該在出現fatal:
之前看到其他信息fatal:
行告訴您發生了什么,例如,無法將主機名解析為IP地址,所需的用戶名和/或密碼,但丟失等等。 使用它來診斷不良連接。 如果連接成功 ,但是主機說“這里沒有Git存儲庫”,請使用可以獲得的有關主機的任何信息來找出存儲庫的去向(例如,您可以直接登錄到主機並四處逛逛嗎?)。
現在,關於assume-unchanged
和skip-worktree
位,恐怕這會變得有些復雜和技術性。 你需要知道一些這方面使用Git的,所以這是值得學習的。 我在這里還指出,使用--really-refresh
的建議基本上是錯誤的。 出於更新索引中的緩存stat數據的目的,這確實暫時忽略了assume-unchanged
位,但是對實際的假設不變的位沒有影響。 清除該位的方法確實是使用--no-assume-unchanged
,如您在上面引用的幻想管道中,以| xargs -0 git update-index --no-assume-unchanged
結尾| xargs -0 git update-index --no-assume-unchanged
| xargs -0 git update-index --no-assume-unchanged
。 skip-worktree位也一樣,除了使用--no-skip-worktree
清除它--no-skip-worktree
。 1個
git update-index
命令在做什么? 重要的是要認識到,在使用Git時,您擁有三個我喜歡隨時調用每個文件的活動副本的文件。 2這三個副本之一就是您簽出的那個提交中的任何一個。 此副本嚴格是只讀的。 您無法更改它:它會被凍結為一個提交,並且只要該提交本身存在(基本上永久),它將一直保留在該提交中。 3這意味着凍結的副本是安全的:您所做的任何事情都不會破壞它; 您總能取回它。 要查看名為path/to/file.ext
的文件的凍結副本,請使用git show HEAD:path/to/file.ext
。 HEAD:file
語法與git show
,可讓您查看當前提交中的凍結副本。 (您也可以在任何其他提交中看到凍結的副本。)
現在,這些凍結副本采用特殊的只讀,僅Git壓縮格式。 您計算機上的其他程序均無法直接訪問它們(除非它們對Git內部了解得太多)。 而且,由於無法更改它們,因此可以很好地進行存檔,但是對於完成任何實際的新工作卻毫無用處。 因此,當您git checkout
某些特定的提交時,Git會提取所有凍結的文件,並將它們恢復為正常的日常文件,您可以照常查看和使用它們。 您可以更改這些普通的讀/寫文件,或對它們執行任何所需的操作,包括添加新文件和刪除現有文件,所有這些操作都與使用計算機執行任何操作一樣。
這些可用的,可用的文件位於Git所謂的工作樹中 。 那就是您完成工作的地方。 那是每個文件的第二個副本。 您不必在這里做任何特別的事情:這些只是文件。 如果你想看看文件命名file
,使用任何工具(編輯,文件瀏覽器等),您總是用它來查看文件命名file
。 它的名字就是file
。
每個文件的第三個副本是Git偷偷摸摸的地方。 這就是索引的來源。索引也稱為暫存區域 ,或者有時(有時是最近) 緩存 。 這些都是同一事物的名稱。 每個文件的第三個副本都在索引中 ,您可以使用git show :file
查看名為file
的文件的索引副本。 也就是說, git show
將冒號放在前面意味着: 給我看一下索引中的副本。 您在花式管道中使用的git ls-files
命令還會列出索引中的內容。
文件的第三個副本采用Git用於永久凍結文件存儲的格式 ,但並沒有完全凍結。 您可以隨時覆蓋它。 您可以用任何喜歡的新內容替換file
的索引副本。 您可以使用git add
執行此操作,它會獲取工作樹副本(大概您已經更改了該副本),並用該版本替換了索引副本。 或者,你可以,如果你喜歡, 請取出的索引拷貝file
,使用git rm
,這將同時刪除索引副本和工作樹副本。
從技術上講,索引中的內容只是有關文件的大量緩存數據,加上一堆標志,以及對文件的存儲的凍結格式副本的引用。 首次簽出某些提交以使HEAD
和工作樹副本匹配時,索引副本實際上只是直接重用凍結的HEAD
副本,因此根本不占用額外的空間。 當您使用git add
覆蓋它時,Git會獲取工作樹副本,將其壓縮為凍結的,隨時可存儲的副本,並將該副本放置在4處並更新索引引用。
這是使git commit
如此快速git commit
的秘密之一。 Git不必查看您的工作樹。 它不必重新壓縮所有文件。 他們已經在您的索引中,准備就緒了。 git commit
要做的就是將預凍結的文件打包成一個commit。 它只是在運行git commit
索引中的內容。 因此,考慮這一點的一種好方法是索引是您建議的下一次提交 。 git add
和git rm
所做的是更新您建議的提交 。 運行git commit
只是可以快照索引中的內容(在登台區域中,隨時可以提交),即使這與上一次提交幾乎相同。 git add
和git rm
命令是實際更新索引的內容。
這就是為什么以及每次提交都是每個文件的完整快照的原因。 您不更新的任何文件仍在索引中(“正在執行中”),並且將在下一次提交中。
git status
使用標志 假設您在當前已檢出的提交(因此在工作樹中)中有3000個文件,並且在工作樹中更改了一個文件並git add
它以使其在索引/登台區域中得到更新。 如果您現在運行git status
,則git status
不會告訴您3000個文件中的 2999個是相同的 ,因為這不是有用的信息。 git status
告訴您的是一個文件已更新。
git status
這樣做的方法至少在原則上至少是運行兩個單獨的比較:
首先, git status
會將HEAD
提交中的每個文件與索引中的副本進行比較。 對於此處相同的每個文件,它什么也沒有說。 但是,如果文件在此處不同 ,則表示: 進行提交 。
接下來, git status
將索引中的每個文件與工作樹中的副本進行比較。 同樣,如果文件相同 ,則什么也沒說。 如果文件不同 ,則表示: 未暫存為commit 。
當git status
此比較時,由於Git內部將文件內容表示為Blob哈希ID,所以第一部分進展很快。 因此,實際上,只是比較每個文件。 只需幾毫秒即可確定3000個文件中的2999個相同而一個不同。 但是第二部分很慢:實際上比較所有3000個文件可能需要幾秒鍾!
因此, git status
作弊。 這就是索引的緩存方面發揮作用的地方。 每個索引條目均包含對已准備好提交的凍結格式文件的引用。 但是它也保存一些來自OS lstat
系統調用的數據。 5 Git可以在工作樹中的文件上執行另一個lstat
系統調用。 在大多數情況下, 當且僅當工作樹中的文件仍與 Git具有凍結格式(由索引條目緩存)的副本相同時 ,結果stat
數據才與Git先前保存的內容匹配。 如果您修改了工作樹副本,則操作系統還將更新stat
數據。
因此,假設您是git status
,將索引中的每個文件與其在工作樹中的副本進行比較,以便可以說如果有必要,則暫不進行提交 。 您可以打開每個工作樹文件並通讀文件,並將其內容與解壓縮凍結的索引副本時得到的內容進行比較。 這將告訴您它們是相同還是不同,但是哇,這是很多工作,可能要花幾秒鍾 。 但是,您已經緩存了此stat
數據,如果將統計數據與另一個lstat
的結果進行比較,那么這將節省大量的工作和時間。 因此,您改為這樣做。 如果lstat
結果與緩存的結果匹配,則文件必須相同,並且您什么也不能說,而是繼續下一個文件。
但是實際上,每個lstat
系統調用也相當慢。 當然,它比讀取每個文件快數千倍,但仍可能需要數百微秒。 而且,如果操作系統具有耗時3 毫秒的可怕的非常慢的lstat
怎么辦? 對3000個文件執行此操作,如果每個文件花費3毫秒,則將花費9 秒 ,這太長了!
Git對此有一個標記。 --assume-unchanged
標志(在每個索引條目中都是可設置的標志)告訴Git: 不要打擾在此工作樹副本上調用lstat
,只需假設它與緩存的stat數據匹配即可 。 它具有第二個功能更強大的標志--skip-worktree
,它可以實現相同的結果。 (它稍微強大一點,因為某些命令(例如git update-index --really-refresh
)將忽略第一個標志,而不會忽略第二個標志。)
如果您將其設置為任意一位,則該操作會將索引的緩存stat
數據與工作樹中的實際stat
數據進行比較,以判斷該文件是否確實被修改,只需假設該文件未被修改即可。 清除兩個位,這些Git操作將最終調用stat
。 然后, 只要操作系統返回的stat
數據也已更新, git status
就會看到該文件的更新。 有一些操作系統級別的技巧可以解決這些問題,但是您通常可以使用touch
來擊敗這些操作系統級別的技巧:
touch path/to/file
確保path/to/file
上的stat
數據現在比Git可能保存的任何緩存的stat
數據都新。
如果有點復雜,此圖片應該足夠清晰:索引/登台區域保存來自上一個lstat
系統調用的有關每個工作樹文件的緩存數據。 如果緩存的數據與OS在新的 lstat
調用中報告的數據匹配,則索引副本必須與工作樹副本匹配。 如果設置了標志位,則Git不會打擾lstat
調用:它只是假設兩組數據匹配,因此索引副本與工作樹副本匹配,而這是否真的成立。 清除這些位后,Git返回調用lstat
並(我們希望)從操作系統獲得准確的報告。
由於Git現在還具有使用文件系統監視器來避免不必要地調用lstat
的能力,因此該圖片不再完全正確。 但這完全是另一個問題的話題。
1請注意,在某些版本的grep
,花哨管道假定您已將LC_COLLATE
設置為C
,並且遵循LC_COLLATE
標志。 那是:
git ls-files -v | grep '^[a-z]'
可能會根據LC_COLLATE
列出每個文件。 它還列出了--skip-worktree
文件,但是您必須使用單獨的git update-index --no-skip-worktree
命令取消設置該標志。 這是我寫git-flagged
原因之一。 (由於grep
匹配太多而列出的文件太多是無害的:您只需調用一些git update-index
命令,這些命令實際上並不需要運行。)
我尚未使git-flagged
腳本支持新的fsmonitor有效/無效位。 如果您的系統使用的是fsmonitor,而這出了問題,那么您會遇到更大的問題,也許應該通過git config
和core.fsmonitor
設置在全局禁用fsmonitor。
2這假設一個正常的(不是--bare
)存儲庫,並且您尚未使用git worktree add
添加其他工作樹。 您使用git worktree add
添加的每個工作樹都有自己的索引和工作樹以及自己的HEAD
,因此每個工作樹都會得到另外三個活動副本。
3提交並獲取特定的哈希ID后,就可以使用該哈希ID來查看該提交是否仍然存在。 如果確實存在(並且可能確實存在),那么您凍結到其中的文件也將以該凍結形式存在。
要真正擺脫錯誤的提交有點困難。 它是可以做到的,所以提交並不一定要永遠永久 ,但這是思考它們的一種方式。
4 “某處”實際上直接進入存儲庫。 如果提交該文件的副本,則將使用凍結的副本;否則,將使用凍結的副本。 如果不是這樣,那么Git 最終會清理掉通常只是剩下的垃圾。 除非您的磁盤空間一直很短,否則您不必擔心git fsck
將顯示為懸掛的blob 。 只是讓Git稍后自行清理它們。
5這特別是指POSIX lstat
系統調用,該系統調用會生成stat
數據。 如果您的基礎操作系統沒有或不使用stat
數據,則Git仍需要緩存某些內容,並將使用某種綜合stat
數據,這些數據需要足夠好才能完成其余工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.