[英]Git: How to revert 2 files that are stubbornly stuck at "Changed but not committed"?
我有一個 repo,其中有兩個文件,據說我在本地更改了這些文件。
所以我堅持這個:
$ git status
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: dir1/foo.aspx
# modified: dir2/foo.aspx
#
no changes added to commit (use "git add" and/or "git commit -a")
執行git diff
表示整個文件內容都已更改,即使從目測看來這似乎是不真實的(似乎存在 diff 似乎無法看到的公共行范圍)。
有趣的是,我不記得在本地更改過這些文件。 此回購與一個遠程回購(私有,地址為 GitHub.com,FWIW)一起使用。
無論我嘗試過什么,我都無法放棄這些本地更改。 我已經嘗試了所有:
$ git checkout -- .
$ git checkout -f
$ git checkout -- dir1/checkout_receipt.aspx
$ git reset --hard HEAD
$ git stash save --keep-index && git stash drop
$ git checkout-index -a -f
換句話說,我已經嘗試了How do I discard unstaged changes in Git? 中描述的所有內容。 加上更多。 但是這 2 個文件仍然停留在“已更改但未提交”狀態。
到底是什么導致兩個文件像這樣卡住並且看似“un-revert-table”?
PS 在上面顯示我已經嘗試過的命令的列表中,我錯誤地寫了git revert
而我的意思是git checkout
。 很抱歉,也感謝那些回答我應該嘗試checkout
的人。 我編輯了問題以更正它。 我確實已經嘗試checkout
了。
我花了幾個小時試圖解決一個類似的問題——我簽出的一個遠程分支,它頑固地將四個文件顯示為“已更改但未更新”,即使刪除所有文件並再次運行git checkout -f
(或其他變體)郵政)!
這四個文件是必需的,但肯定沒有被我修改過。 我的最終解決方案 - 說服 Git 他們沒有被改變。 以下適用於所有簽出的文件,顯示“修改”狀態 - 確保您已經提交/隱藏了任何真正被修改的文件::
git ls-files -m | xargs -i git update-index --assume-unchanged "{}"
在 Mac OSX 上,但是 xargs 的操作有點不同(感謝 Daniel 的評論):
git ls-files -m | xargs -I {} git update-index --assume-unchanged {}
我已經將此添加為下次自己的占位符,但我希望它也對其他人有所幫助。
-鋁
文件中的行尾是什么? 我打賭他們是CRLF。 如果是,請查看本指南: http://help.github.com/line-endings/
簡而言之,您需要確保 git 設置為在提交時將行尾轉換為 LF,然后提交這些文件。 假設您正確設置 git,repo 中的文件應該始終是 LF,簽出的文件應該是操作系統的原生文件。
這就是我解決相同問題的方法: open.gitattributes 更改:
* text=auto
至:
#* text=auto
保存並關閉,然后恢復或重置,感謝@Simon East 的提示
另一種可能性是差異(阻止您使用簽出命令恢復這些文件)是文件模式之一。 這就是發生在我身上的事情。 在我的 git 版本上,您可以使用
git diff dir1/foo.aspx
它會向您顯示文件模式更改。 但是,它仍然不會讓您還原它們。 為此使用
git 配置 core.filemode false
或通過添加在文本編輯器中更改 git.config
[核]
filemode = false
完成此操作后,您可以使用
git 重置 HEAD dir1/foo.aspx
並且文件應該消失。
我有一些幻像更改的文件顯示為已修改,但實際上是相同的。
運行此命令有時會起作用:
(關閉 git 的“智能”但通常無用的行尾轉換)
git config --local core.autocrlf false
但在另一種情況下,我發現這是由於根目錄中的.gitattributes
文件存在一些行尾設置,即使它被關閉,它也試圖對某些文件應用autocrlf
。 這實際上並沒有幫助,所以我刪除.gitattributes
並提交,並且文件不再顯示為已修改。
嘗試還原本地更改:
git checkout -- dir1/foo.aspx
git checkout -- dir2/foo.aspx
我認為提供有關如何重現問題的提示會很有幫助,以便更好地理解問題:
$ git init
$ echo "*.txt -text" > .gitattributes
$ echo -e "hello\r\nworld" > 1.txt
$ git add 1.txt
$ git commit -m "committed as binary"
$ echo "*.txt text" > .gitattributes
$ echo "change.." >> 1.txt
# Ok let's revert now
$ git checkout -- 1.txt
$ git status
modified: 1.txt
# Oooops, it didn't revert!!
# hm let's diff:
$ git diff
warning: CRLF will be replaced by LF in 1.txt.
The file will have its original line endings in your working
directory.
diff --git a/1.txt b/1.txt
index c78c505..94954ab 100644
--- a/1.txt
+++ b/1.txt
@@ -1,2 +1,2 @@
-hello
+hello
world
# No actual changes. Ahh, let's change the line endings...
$ file 1.txt
1.txt: ASCII text, with CRLF line terminators
$ dos2unix 1.txt
dos2unix: converting file 1.txt to Unix format ...
$ git diff
git diff 1.txt
diff --git a/1.txt b/1.txt
index c78c505..94954ab 100644
--- a/1.txt
+++ b/1.txt
@@ -1,2 +1,2 @@
-hello
+hello
world
# No, it didn't work, file is still considered modified.
# Let's try to revert for once more:
$ git checkout -- 1.txt
$ git status
modified: 1.txt
# Nothing. Let's use a magic command that prints wrongly committed files.
$ git grep -I --files-with-matches --perl-regexp '\r' HEAD
HEAD:1.txt
第二種重現方式:在上面的腳本中替換這一行:
echo "*.txt -text" >.gitattributes
和git config core.autocrlf=false
並保持線路的 rest 原樣
以上都說了什么? 可以(在某些情況下)使用 CRLF 提交文本文件(例如-text
/ 或core.autocrlf=false
中的.gitattributes
)。
當我們稍后想要將相同的文件視為文本( -text
-> text
)時,將需要再次提交。
當然,您可以暫時恢復它(如Abu Assar正確回答)。 在我們的例子中:
echo "*.txt -text" > .gitattributes
git checkout -- 1.txt
echo "*.txt text" > .gitattributes
答案是:你真的想這樣做嗎,因為每次更改文件都會導致同樣的問題。
作為記錄:
要檢查哪些文件會在您的 repo 中導致此問題,請執行以下命令(git 應使用 --with-libpcre 編譯):
git grep -I --files-with-matches --perl-regexp '\r' HEAD
通過提交文件(假設您想將它們視為文本),這與執行此鏈接http://help.github.com/line-endings/中建議的操作相同,以解決此類問題. 但是,您無需刪除.git/index
並執行reset
,您只需更改文件,然后執行git checkout -- xyz zyf
然后提交。
您也可能遇到與目錄命名字母大小寫有關的問題。 您的一些同事可能已經將目錄的名稱從例如myHandler 更改為MyHandler 。 如果您稍后推送和拉取原始目錄的一些文件,您將在遠程存儲庫上有2 個單獨的目錄,而在您的本地計算機上只有一個目錄,因為在 Windows 上您只能有一個。 而你有麻煩了。
要檢查是否是這種情況,只需查看遠程存儲庫是否具有雙重結構。
要解決此問題,請在 repo 之外制作父目錄的備份副本,然后刪除父目錄,推送它。 拉動(此時標記為已刪除的第二個應該出現在狀態上)並再次推動。 之后,從備份中重新創建整個結構並再次推送更改。
我遇到了同樣的問題,有趣的是,文件在 windows 上發生了更改,但從 WSL 中查看時卻沒有。 再多的亂七八糟的行尾、重置等都無法改變它。
最終,我在這個答案中找到了解決方案。 以下是為方便起見的文字:
我已經使用以下步驟解決了這個問題
1) 從 Git 的索引中刪除每個文件。
git rm --cached -r .
2) 重寫 Git 索引以獲取所有新行結尾。
git reset --hard
解決方案是 git 站點https://help.github.com/articles/dealing-with-line-endings/上描述的步驟的一部分
這個問題也可能是因為 git 將大小寫差異視為不同的文件,但 windows 將它們視為同一個文件。 如果文件名只是改變了大小寫,那么該 repo 的每個 windows 用戶最終都會遇到這種情況。
解決方法是確認文件內容正確,然后重新提交。 我們不得不將這兩個文件的內容合並在一起,因為它們是不同的。 然后拉,會有一個合並沖突,你可以通過刪除重復文件來解決。 重新提交合並分辨率,您將回到穩定的 state。
git checkout dir1/foo.aspx
git checkout dir2/foo.aspx
對我來說,問題不在於行尾。 這是關於更改文件夾名稱的大小寫(Reset_password -> Reset_Password)。 這個解決方案幫助了我: https://stackoverflow.com/a/34919019/1328513
我的問題是別的。 沒有多少reset
、 clean
、 restore
或其他 git 命令解決了我的問題。 我也試過刪除文件,恢復等,每次拉,它都會回來。
> git status
On branch master
Your branch is behind 'origin/master' by 319 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: bucket/stellarium.json
我通過以下方式修復了它:
重命名/將文件移開。 (-->不是git mv
)
> mv .\bucket\stellarium.json .\bucket\stellarium_DELETEME.json
> git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: bucket/stellarium.json
Untracked files:
(use "git add <file>..." to include in what will be committed)
bucket/stellarium_DELETEME.json
恢復文件。
> git restore .\bucket\stellarium.json
> git status
On branch master
Your branch is up to date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
bucket/stellarium_DELETEME.json
刪除重命名的文件。
> rm .\bucket\stellarium_DELETEME.json
> git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
所以... ?
也許磁盤的 FAT 搞砸了? 我不確定。 還是不知道。 但是,它奏效了。
去過那里,時間一直是我最大的敵人之一,所以決定用最簡單的解決方案 go。
簡短回答:檢查.gitattibutes
是否有任何可能影響有問題的文件的設置。
對我來說, .gitattributes
中有一個設置,對某些特定文件強制執行eol=crlf
crlf:
*.bat text eol=crlf
crlf 添加它是為了強制那些文件在crlf
中具有 crlf。
我不得不評論那一行:
#*.bat text eol=crlf
我使用 macOS,每當我切換分支時都會出現問題。 在評論此設置之前,我必須執行git rm --cached -r.
每次都進行硬重置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.