[git] Unstaged changes left after git reset --hard

After git reset --hard, git status gives me files within the Changes not staged for commit: section.

I've also tried git reset ., git checkout -- . and git checkout-index -f -a, to no avail.

So, how can I get rid of those unstaged changes?

This seems to hit only Visual Studio project files. Weird. See this paste: http://pastebin.com/eFZwPn9Z. What is special with those files, is that in .gitattributes I have:

*.sln        eol=crlf
*.vcproj     eol=crlf
*.vcxproj*   eol=crlf

Also, autocrlf is set to false in my global .gitconfig. Could that be somehow relevant?

This question is related to git git-reset

The answer is


RESOLVED!!!

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/


I hit a similar issue also involving .gitattributes, but for my case involved GitHub's LFS. While this isn't exactly the OP's scenario, I think it provides an opportunity to illustrate what the .gitattributes file does and why it can lead to unstaged changes in the form of "phantom" differences.

In my case, a file already was in my repository, like since the beginning of time. In a recent commit, I added a new git-lfs track rule using a pattern that was in hindsight a bit too broad, and ending up matching this ancient file. I know I didn't want to change this file; I know I didn't change the file, but now it was in my unstaged changes and no amount of checkouts or hard resets on that file was going to fix it. Why?

GitHub LFS extension works primarily through leveraging the hooks that git provides access through via the .gitattributes file. Generally, entries in .gitattributes specify how matching files should be processed. In the OP's case, it was concerned with normalizing line endings; in mine, it was whether to let LFS handle the file storage. In either case, the actually file that git sees when computing a git diff does not match the file that you see when you inspect the file. Hence, if you change how a file is processed via the .gitattributes pattern that matches it, it will show up as unstaged changes in the status report, even if there really is no change in the file.

All that said, my "answer" to the question is that if the change in .gitattributes file is something you wanted to do, you should should really just add the changes and move on. If not, then amend the .gitattributes to better represent what you want to be doing.

References

  1. GitHub LFS Specification - Great description of how they hook into the clean and smudge function calls to replace your file in the git objects with a simple text file with a hash.

  2. gitattributes Documentation - All the details on what is available to customize how git processes your documents.


You can stash away your changes, then drop the stash:

git stash
git stash drop

Run clean command:

# Remove all untracked files and directories. (`-f` is `force`, `-d` is `remove directories`)

git clean -fd

Another possibility that I encountered was that one of the packages in the repository ended up with a detached HEAD. If none of the answer here helps and you encounter a git status message like this you might have the same problem:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   path/to/package (new commits)

Going into the path/to/package folder a git status should yield the following result:

HEAD detached at 7515f05

And the following command should then fix the issue, where master should be replaced by your local branch:

git checkout master

And you'll get a message that your local branch will be some amounts of commits behind the remote branch. git pull and you should be out of the woods!


In a similar situation. As a result of many years of torment with many programmers who were able to stuff different encodings of the ends of lines (.asp, .js, .css ... not the essence) into one file. Some time ago refused .gitattributes. Settings for repo left autorclf = true andsafecrlf = warn.

The last problem arose when synchronizing from the archive with different ends of lines. After copying from the archive, in the git status many files are changed with the note

The line will have its original line endings in your working directory. warning: LF will be replaced by CRLF in ...

Tips from How to normalize working tree line endings in Git? helped

git add -u


If other answers are not working, trying adding the files, then resetting

$ git add -A
$ git reset --hard

In my case, this helped when there were a bunch of empty files that git was tracking.


I had the same problem. I did git reset --hard HEAD but still every time I did git status I was seeing some files as modified.

My solution was relatively simple. I just closed my IDE (here it was Xcode) and close my command line (here it was terminal on my Mac OS) and tried it again and it worked .

Yet I was never able to find what originated the problem.


Another cause for this might be case-insensitive file systems. If you have multiple folders in your repo on the same level whose names only differ by case, you will get hit by this. Browse the source repository using its web interface (e.g. GitHub or VSTS) to make sure.

For more information: https://stackoverflow.com/a/2016426/67824


I had the same problem and it was related to the .gitattributes file. However the file type that caused the problem was not specified in the .gitattributes.

I was able to solve the issue by simply running

git rm .gitattributes
git add -A
git reset --hard

Git won't reset files that aren't on repository. So, you can:

$ git add .
$ git reset --hard

This will stage all changes, which will cause Git to be aware of those files, and then reset them.

If this does not work, you can try to stash and drop your changes:

$ git stash
$ git stash drop

I believe that there is an issue with git for Windows where git randomly writes the wrong line endings on checkout and the only workaround is to checkout some other branch and force git to ignore changes. Then checkout the branch you actually want to work on.

git checkout master -f
git checkout <your branch>

Be aware that this will discard any changes you might have intentionally made, so only do this if you have this problem immediately after checkout.

Edit: I might have actually got lucky the first time. It turns out that I got bit again after switching branches. It turned out that the files git was reporting as modified after changing branches was changing. (Apparently because git was not consistently applying the CRLF line ending to files properly.)

I updated to the latest git for Windows and hope the problem is gone.


None of these methods worked for me, the only solution was to nuke the whole repo and re-clone it. This includes stashing, resetting, adding then resetting, clrf settings, case sensitivity etc. Sigh..


Possible Cause #1 - Line Ending Normalization

One situation in which this can happen is when the file in question was checked into the repository without the correct configuration for line endings (1) resulting in a file in the repository with either the incorrect line endings, or mixed line endings. To confirm, verify that git diff shows only changes in line endings (these may not be visible by default, try git diff | cat -v to see carriage returns as literal ^M characters).

Subsequently, someone probably added a .gitattributes or modified the core.autocrlf setting to normalize line endings (2). Based on the .gitattributes or global config, Git has applied local changes to your working copy that apply the line ending normalization requested. Unfortunately, for some reason git reset --hard does not undo these line normalization changes.

Solution

Workarounds in which the local line endings are reset will not solve the problem. Every time the file is "seen" by git, it will try and reapply the normalization, resulting in the same issue.

The best option is to let git apply the normalization it wants to by normalizing all the line endings in the repo to match the .gitattributes, and committing those changes -- see Trying to fix line-endings with git filter-branch, but having no luck.

If you really want to try and revert the changes to the file manually then the easiest solution seems to be to erase the modified files, and then to tell git to restore them, although I note this solution does not seem to work consistently 100% of the time (WARNING: DO NOT run this if your modified files have changes other than line endings!!):

    git status --porcelain | grep "^ M" | cut -c4- | xargs rm
    git checkout -- .

Note that, unless you do normalize the line endings in the repository at some point, you will keep running into this issue.

Possible Cause #2 - Case Insensitivity

The second possible cause is case insensitivity on Windows or Mac OS/X. For example, say a path like the following exists in the repository:

/foo/bar

Now someone on Linux commits files into /foo/Bar (probably due to a build tool or something that created that directory) and pushes. On Linux, this is actually now two separate directories:

/foo/bar/fileA
/foo/Bar/fileA

Checking this repo out on Windows or Mac may result in modified fileA that cannot be reset, because on each reset, git on Windows checks out /foo/bar/fileA, and then because Windows is case insensitive, overwrites the content of fileA with /foo/Bar/fileA, resulting in them being "modified".

Another case may be an individual file(s) that exists in the repo, which when checked out on a case insensitive filesystem, would overlap. For example:

/foo/bar/fileA
/foo/bar/filea

There may be other similar situations that could cause such problems.

git on case insensitive filesystems should really detect this situation and show a useful warning message, but it currently does not (this may change in the future -- see this discussion and related proposed patches on the git.git mailing list).

Solution

The solution is to bring the case of files in the git index and the case on the Windows filesystem into alignment. This can either be done on Linux which will show the true state of things, OR on Windows with very useful open source utility Git-Unite. Git-Unite will apply the necessary case changes to the git index, which can then be committed to the repo.

(1) This was most likely by someone using Windows, without any .gitattributes definition for the file in question, and using the default global setting for core.autocrlf which is false (see (2)).

(2) http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/


For some reason

git add .

didn't work, but

$ git add -A

worked out!


If you use Git for Windows, this is likely your issue

I've had the same problem and stash, hard reset, clean or even all of them was still leaving changes behind. What turned out to be the problem was the x file mode that was not set properly by git. This is a "known issue" with git for windows. The local changes show in gitk and git status as old mode 100755 new mode 100644, without any actual file differences.

The fix is to ignore the file mode:

git config core.filemode false

More info here


try to simply git restore .

That's what git says & it's working


Check your .gitattributes.

In my case I have *.js text eol=lf in it and git option core.autocrlf was true.

It brings me to the situation when git autoconverts my files line endings and prevent me to fix it and even git reset --hard HEAD didn`t do anything.

I fix it with commenting *.js text eol=lf in my .gitattributes and uncommented it after it.

Looks like it just git magic.


Similar issue, although I'm sure only on surface. Anyway, it may help someone: what I did (FWIW, in SourceTree): stashed the uncommitted file, then did a hard reset.


As other answers have pointed out, the problem is because of line-end auto correcting. I encountered this issue with *.svg files. I used svg file for icons in my project.

To solve this issue, I let git know that svg files should be treated as binary instead of text by adding the below line to .gitattributes

*.svg binary