簡體   English   中英

Git:如何恢復 2 個頑固地停留在“已更改但未提交”的文件?

[英]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 忽略模式更改(chmod)的答案中得到了所有這些?

我有一些幻像更改的文件顯示為已修改,但實際上是相同的。

運行此命令有時會起作用:
(關閉 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

我的問題是別的。 沒有多少resetcleanrestore或其他 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。

  1. 將 2 個本地版本文件移至別處
  2. 提交並推送
  3. 手動將文件復制到 git 服務器

簡短回答:檢查.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM