108

I have a repo that has two files that supposedly I changed locally.

So I'm stuck with this:

$ 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")

Doing git diff says that the entire file contents have changed, even though from eyeballing it that seems untrue (there seem to be common line ranges that diff seems to be failing to see).

Interestingly I don't remember changing these files locally. This repo is used with one remote repo (private, at GitHub.com, FWIW).

No matter what I've tried, I can't discard these local changes. I have tried all of:

$ 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

In other words I've tried everything described in How do I discard unstaged changes in Git? plus more. But the 2 files remain stuck as "changed but not committed".

What the heck would cause two files to be stuck like this and seemingly "un-revert-table"??

P.S. In the list above showing commands I'd already tried, I mistakenly wrote git revert when I meant git checkout. I'm sorry and thank you to those of you who answered that I should try checkout. I edited the question to correct it. I definitely did already try checkout.

Community
  • 1
  • 1
Greg Hendershott
  • 16,100
  • 6
  • 36
  • 53
  • Does `git diff --ignore-space-change` or `git diff --ignore-all-space` make a difference in the output of `git diff`? – jdd Jun 13 '11 at 22:51
  • @jermiahd Yes! With either flag, `git diff` says the files are identical. – Greg Hendershott Jun 13 '11 at 23:37
  • 2
    Possible duplicate of http://stackoverflow.com/questions/2016404/git-status-shows-modifications-git-checkout-file-doesnt-remove-them. I like the accepted answer there better anyway, which is to set `git config --global core.autocrlf false` instead of 'true'. – Johann Aug 01 '13 at 23:17
  • 2
    The answer [here][1] worked for me and many others. [1]: http://stackoverflow.com/questions/2016404/git-status-shows-modifications-git-checkout-file-doesnt-remove-them#answer-18792689 – Mike K Mar 19 '15 at 17:58
  • 2
    This also happens when repository containing 2 or more files in same directory with different case is checked out in case-insensitive file system. Remove or rename one of the file to resolve the issue. –  Jun 07 '16 at 06:18

15 Answers15

177

I spent hours trying to solve a similar issue - a remote branch that I had checked out, which stubbornly showed four files as 'Changed but not updated', even when deleting all files and running git checkout -f again (or other variations from this post)!

These four files were necessary, but certainly hadn't been modified by me. My final solution - persuade Git that they had not been changed. The following works for all checked out files, showing 'modified' status - make sure you have already committed/stashed any that have really been modified!:

git ls-files -m | xargs -i git update-index --assume-unchanged "{}"

On Mac OSX, however xargs operates a little bit different (thx Daniel for the comment):

git ls-files -m | xargs -I {} git update-index --assume-unchanged {}

I've added this as a placeholder for myself for next time.

starball
  • 20,030
  • 7
  • 43
  • 238
Alan Forsyth
  • 2,317
  • 2
  • 12
  • 7
  • 14
    I had a couple of stubborn files and ran this command, git status now shoes no changes, but when I try to change branch git still tells me I can't change branch because those two files have local changes. Not sure what I've done wrong but it seemed it just covered up the problem rather than fixing it? I also couldn't commit the files after running that command. Solution for me was to delete them, commit and swap branches. – RodH257 Nov 07 '13 at 00:04
  • 6
    thanks! I tried ALL tricks mentioned in every other answer I could find - none worked. on a mac couldn't use the line as is, just ran git update-index --assume-unchanged on each file and this made the issue go away. – Yonatan Karni Jun 25 '14 at 11:28
  • 2
    Isn't the "--assume-unchanged" option supposed to be used when you want local modifications on this file to NEVER be commited? Like when you checkout a template website config file and update it with sensitive infos which should not be stored in the repository? – Maxime Rossini Nov 21 '14 at 21:48
  • @RodH257 For future readers: I did the same, but I was able to delete the files without committing, and switch branches. – Daniel Neel Mar 02 '15 at 20:16
  • 7
    This is exactly what I needed, though xargs on the mac seems to operate a bit differently (I'm running 10.10 Yosemite). This finally worked for me: `git ls-files -m | xargs -I {} git update-index --assume-unchanged {}` – Daniel Jun 26 '15 at 22:50
  • 1
    after all i found you :P – Mani Mar 16 '16 at 06:19
  • 4
    To revert the effect of the command: `git ls-files -v|grep '^h' | cut -c3- | xargs -i git update-index --no-assume-unchanged "{}"` – Marinos An Apr 04 '17 at 16:54
  • 4
    This solution does not fix the problem. It hides it. There are a couple of things that cannot performed after `assume-unchaged`, as in the case of @RodH257 . I believe the most correct answer for the case where commands like `git checkout -- file` , `git stash` and `git reset --hard HEAD` don't work is, as already answered, editing `.gitattributes` – Marinos An Apr 04 '17 at 18:01
  • I have a weird file (the same path as a legit file in my repo, but all lowercase letters in its path) and tried the "assume unchanged" but like others have said, it just hid the problem. I still had the "you have local changes" error when pulling. To revert this, do a "git update-index --no-assume-unchnaged path/to/your/file" – clamum Dec 20 '21 at 19:14
  • Well it seems a co-worker somehow checked-in this particular file, but his path is in all lowercase somehow (we're both using Windows which is case-insensitive, which a warning message noted about this error when I cloned the repo to a new/fresh directory). The warning upon a fresh clone was: "The following paths have collided (eg case-sensitive paths on a case-insensitive filesystem) and only one from the same colliding group is in the working tree: BaseCMS/Areas/myfile.css ..... basecms/areas/myfile.css" – clamum Dec 20 '21 at 19:30
36

What are the line endings in the files? I'm betting they're CRLF. If they are, check out this guide: http://help.github.com/line-endings/

In short, you need to make sure git is set to convert the line endings to LF on commit, and then commit those files. Files in the repo should always be LF, files checked out should be the OS's native, assuming you set git correctly.

Tekkub
  • 30,739
  • 2
  • 30
  • 20
  • 1
    Thanks. I do already have `git config --global core.autocrlf true` and so does the other party pushing to the repo on GitHub. – Greg Hendershott Jun 13 '11 at 23:39
  • 1
    Then you should just need to do the bits in the last `
    ` block of that guide to fix the files in the repo.
    – Tekkub Jun 14 '11 at 10:06
  • 5
    I disagree that line endings should *always* be LF in repo (especially if someone else has already committed CRLF) and also that OS should be always be native. My Windows editor and environment (mainly for PHP, HTML, CSS etc.) copes perfectly well with LF line endings. – Simon East Feb 12 '16 at 06:39
  • A genius answer, I'd forgotten that I'd recently used gitattributes to force LF in repo files and wasn't expecting git to be auto changing the file. We have a mix of Windows and Linux developers and it was driving us mad as editors on different platforms kept switching out line terminators, once the change has rippled through all this should go away. – Oly Dungey May 20 '16 at 10:07
24

this is how I fixed the same problem in my case: open .gitattributes change:

* text=auto

to:

#* text=auto

read more here https://code.visualstudio.com/docs/remote/troubleshooting#_resolving-git-line-ending-issues-in-containers-resulting-in-many-modified-files

save and close , then revert or reset, thanks to @Simon East for the hint

Handsome Nerd
  • 17,114
  • 22
  • 95
  • 173
Muhammad Assar
  • 659
  • 7
  • 16
  • 2
    Removing the `text=auto` setting in .gitattributes worked for me, and then after I `git reset --hard`, putting that setting back, the files no longer showed as modified! – ErikE Aug 29 '16 at 18:15
  • 1
    There's obviously something wrong with this `text=auto` setting. I am working in repos with commits from multiple OS and I still haven't figured out what causes me more problems: to keep it or to drop it. – Marinos An Apr 04 '17 at 16:42
  • 1
    @MarinosAn yes there is, specifically, git allows you to leave the existing text files with the wrong line endings when you first add this setting. That's just wrong and unless you remember to do that yourself, you will eventually run into one of these un-revertable changes. – Roman Starkov Nov 14 '17 at 09:54
12

Another possibility is that the difference (that's preventing your from reverting these files with a checkout command) is one of file mode. This is what happened to me. On my version of git you can discover this by using

git diff dir1/foo.aspx

And it will show you file mode changes. It still won't let you revert them, though. For that use either

git config core.filemode false

or change your git .config in your text editor by adding

[core]

filemode = false

After you do this, you can use

git reset HEAD dir1/foo.aspx

and the file should disappear.

(I got all of this from the answer to How do I make git ignore mode changes (chmod)?)

Community
  • 1
  • 1
Eyal
  • 3,412
  • 1
  • 44
  • 60
8

I had the same issue, with the interesting addition that the files were changed on windows, but not when looking at them from WSL. No amount of messing around with line endings, resets etc. was able to change it.

Eventually, I found a solution in this answer. Following is the text for convenince:


I have resolved this problem using following steps

1) Remove every file from Git's index.

git rm --cached -r .

2) Rewrite the Git index to pick up all the new line endings.

git reset --hard

Solution was part of steps described on git site https://help.github.com/articles/dealing-with-line-endings/

MCO
  • 1,187
  • 1
  • 11
  • 20
4

This issue can also be cause because git treats capitalization differences as different files but windows treats them as the same file. If a file name only had it's capitalization changed then every windows user of that repo will end up in this situation.

The solution is to confirm the files contents are correct and then recommit it. We had to merge the two files contents together since they were different. Then pull and there will be a merge conflict which you can resolve by deleting the duplicate file. Recommit the merge resolution and you are back to a stable state.

  • 1
    I had this happen on Mac too, just incase anyone else encounters this, its not just a Windows issue. For me the issue was a directory had capitalisation changed and although everything was fine for a number of commits, as soon as a file in that path changed, it got stuck. We had to `git rm` the old path and then add the "new" (existing) path and it all worked itself out – doz87 Jun 17 '21 at 05:50
4

Try to revert local changes:

git checkout -- dir1/foo.aspx
git checkout -- dir2/foo.aspx
Tadeck
  • 132,510
  • 28
  • 152
  • 198
  • I had "revert" on the brain and I meant to write `checkout`. I did already try `checkout`. Thank you anyway for your answer. It was a good answer to my original question so I'll upvote. – Greg Hendershott Jun 13 '11 at 20:17
3

I had some phantom changed files that were showing as modified, but were actually identical.

Running this command sometimes works:
(Turns off git's "smart" but often unhelpful line-ending conversions)

git config --local core.autocrlf false

But in another case I found it was due to a .gitattributes file in the root which had some line-ending settings present, which was trying to apply autocrlf for certain files even when it was turned off. That wasn't actually helpful, so I deleted .gitattributes, committed, and the file no longer showed as modified.

Simon East
  • 55,742
  • 17
  • 139
  • 133
  • Removing the `text=auto` setting in .gitattributes worked for me, and then after I `git reset --hard`, putting that setting back, the files no longer showed as modified! – ErikE Aug 29 '16 at 18:15
2

I think it would be helpful to provide a hint on how to reproduce the issue, in order to better understand the problem:

$ 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

2nd way to reproduce: In the above script replace this line:
echo "*.txt -text" > .gitattributes
with
git config core.autocrlf=false
and keep the rest of the lines as is


What all the above say? A text file can (under some circumstances) be committed with CRLF, (e.g. -text in .gitattributes / or core.autocrlf=false).

When we later want to treat the same file as text (-text -> text) it will need to be committed again.
Of course you can temporarily revert it (as correctly answered by Abu Assar). In our case:

echo "*.txt -text" > .gitattributes
git checkout -- 1.txt
echo "*.txt text" > .gitattributes

The answer is: do you really want to do that, because it's gonna cause the same problem everytime you change the file.


For the record:

To check which files can cause this problem in your repo execute the following command (git should be compiled with --with-libpcre):

git grep -I --files-with-matches --perl-regexp '\r' HEAD

By committing the file(s) (supposing that you want to treat them as text), it is the same thing as doing what is proposed in this link http://help.github.com/line-endings/ for fixing such problems. But, instead of you removing .git/index and performing reset, you can just change the file(s), then perform git checkout -- xyz zyf and then commit.

Marinos An
  • 9,481
  • 6
  • 63
  • 96
2

You also might have had a problem related to directories naming letter cases. Some of your colleagues could have changed the name of the directory from e.g. myHandler to MyHandler. If you later on pushed and pulled some of the files of the original directory you would have had 2 separate directories on the remote repository AND only one on your local machine since on Windows you only can have just one. And you're in trouble.

To check if that is the case, just see if the remote repository has double structure.

To fix this, make a backup copy of the parent directory outside of the repo, then delete the parent directory, push it. Make a pull (here's when the second one marked as deleted should appear on status) and push again. After that, recreate the whole structure from your backup and push the changes again.

Reversed Engineer
  • 1,095
  • 13
  • 26
smexy
  • 91
  • 1
  • 2
2
git checkout dir1/foo.aspx
git checkout dir2/foo.aspx
Steve Prentice
  • 23,230
  • 11
  • 54
  • 55
  • I had "revert" on the brain and I meant to write `checkout`. I did already try `checkout`. Thank you anyway for your answer. It was a good answer to my original question so I'll upvote. – Greg Hendershott Jun 13 '11 at 20:16
1

For me the issue was not about line endings. It was about changing case in folder name (Reset_password -> Reset_Password). This solution helped me: https://stackoverflow.com/a/34919019/1328513

Zhenya
  • 6,020
  • 6
  • 34
  • 42
1

My issue was something else. No amount of reset, clean, restore, or other git commands resolved my issue. I also tried deleting the file, reverting, etc., and every time I pulled, it would come right back.

> 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

I fixed it by the following:

Rename / move the file out of the way. (--> Not 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

Restore the file.

> 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

Delete the renamed file.

> 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

So... ?

Perhaps the disk's FAT got screwed up? I'm not sure. Still don't know. But, it worked.

kodybrown
  • 2,337
  • 26
  • 22
0

Been there, time has always been one of my greatest enemy so decided to go with the easiest solution.

  1. move the 2 local version files elsewhere
  2. Commit and push
  3. copy the files manually to the git server
  4. pull
0

Short answer: check .gitattibutes for any setting that might affect the files that have problems.

For me there was a setting in .gitattributes forcing eol=crlf for some specific files:

*.bat text eol=crlf That was added to force those files have crlf in Windows.

I had to comment that line:

#*.bat text eol=crlf

I use macOS, the problem showed up whenever I was switching branches. Before commenting this setting I had to do a git rm --cached -r . and a hard reset every time.

Florin Dobre
  • 9,872
  • 3
  • 59
  • 93