18

I've previously been able to undo changes through SourceTree by performing the "Discard" function, which under the hood produces this command:

git -c diff.mnemonicprefix=false -c core.quotepath=false reset -q HEAD -- myproj.csproj 
git -c diff.mnemonicprefix=false -c core.quotepath=false checkout HEAD -- myproj.csproj

Suddenly this doesn't work. I do the Discard, no error occurs, refreesh the view, but the files are still "modified". I've then tried to do the same in the command line with the following, same result:

c:\myproject> git reset HEAD

Unstaged changes after reset:
M       myproj.csproj

Why is it still listed as an unstaged change?

I've verified that the file is indeed writable (no process is holding a lock)

update

git checkout didn't work either:

C:\myproject>git checkout myproj.csproj

C:\myproject>git status
# On branch master
# 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:   myproj.csproj
#
no changes added to commit (use "git add" and/or "git commit -a")

Update 2 Also tried:

  • git checkout --
  • git checkout -- .
  • git checkout HEAD

,none of which solves my problem

update 3 - huge step closer:

Turns out when I do the checkout, the .csproj is indeed reverted to the correct version, but the checked out version uses a different line feed encoding. While the checked-in version has CR-LF (0D-0A) for line feed, the checked-out has only LF (0A). Hence git belives the file to be different on every single line. Why this?

update 4: added the second line of git-commands issued by SourceTree. I didn't notice that the first time around, that's why I thought git reset HEAD would do anything. This doesn't change the fact that the underlying problem still is CR/LF-related (I think)

summary I never found a solution to the issue, but I "solved" it by checking in the file. My original question didn't contain information that SourceTree indeed issued the correct commands to rollback what I wanted, so most answers here address that issue. The real issue is still unclear, but my main theory is that it was CR/LF related.

Nilzor
  • 18,082
  • 22
  • 100
  • 167
  • 1
    possible duplicate of [How do you discard unstaged changes in git?](http://stackoverflow.com/questions/52704/how-do-you-discard-unstaged-changes-in-git) – devnull Jan 23 '14 at 11:35
  • My updated makes it not a duplicate. The answers of that question does not work in my case. Might be a too localized issue though... we'll see. – Nilzor Jan 23 '14 at 11:54
  • The update makes this question suddenly really interesting. – Jerska Jan 23 '14 at 13:19
  • 1
    I'm inclined to give up - "solved" the issue by checking in the new line feed encoding. Neither `git config --global core.autocrlf true` nor `false` helped either. If anyone have any more suggestions, I have a clone of the repo for further testing. – Nilzor Jan 23 '14 at 13:31
  • The "new" line encoding is broken. A Visual Studio project *must have dos line endings*. It won't be correctly read otherwise, at least by some versions. – Jan Hudec Jan 24 '14 at 09:04
  • Very interesting. What is DOS line endings? LF-only? – Nilzor Jan 24 '14 at 09:06
  • http://stackoverflow.com/questions/2016404/git-status-shows-modifications-git-checkout-file-doesnt-remove-them – Ohad Schneider May 03 '16 at 09:49
  • 1
    First of all I closed SourceTree. Then I set both core.autocrlf and core.safecrlf to true as was said in comments here - https://stackoverflow.com/questions/1575682/cant-seem-to-discard-changes-in-git. After that I used git reset --hard. Fortunantly, all changes disapeared. – Kate Nov 23 '19 at 21:46

6 Answers6

11

If you need to remove local changes then run following command

git checkout -- file_name

git reset HEAD does not remove local changes.

ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
Thushan
  • 1,220
  • 14
  • 14
  • See update in question. git checkout didn't work either. Is my repo corrupted? – Nilzor Jan 23 '14 at 11:47
  • 1
    I'm accepting this answer because my question was incomplete/unclear in the beginning, and this would indeed solve the initial problem. However noone has provided an answer to the CR/LF-problem – Nilzor Jan 24 '14 at 09:03
7

I suspect that you had files saved with CRLF line endings in your repository, and then somewhere along the way your configuration was changed so that git started normalizing end-of-line characters (either core.autocrlf was set to true, or the .gitAttributes file was added or changed). When I ran into this problem, it turned out that a .gitAttributes file that contained * text=auto had been added to my repo.

(EOL normalization means that git will write the end-of-line characters as LF in its database, regardless of what you use in your working copy).

Git doesn't automatically check your files to see if they require EOL normalization after you enable it. You have to explicitly tell it to check all of your files, or else you end up in this situation: the files in your repository still have CRLF line endings, and git will only notice that it should normalize them when it touches each file. So the next time you commit some changes to a file, git will write the file to its database with LF line endings.

The problem occurs when git touches the file through a read operation. Say you make changes to a file that has CRLF line endings and then try to discard your changes. Git will read the clean copy from its database, see that it has CRLF line endings, and then mark the file as modified. The file has not actually been modified, but git is saying that it wants to write a change to the EOL characters to its database. This happens every time you attempt to discard your changes, check out that file, or even do a hard reset. That is why it seems to be impossible to undo those modifications.

You should have git normalize the line endings on all of your text files, so this problem doesn't continue to pop up (see https://stackoverflow.com/a/4683783/1369 for instructions on how to do that). If it's possible, you might even want to modify your history so the line endings are normalized at the same time the .gitAttributes settings were changed.

If you cannot modify your history, then you may run into situations where you need to check out old versions of your files that still have the CRLF line endings. You will probably get stuck with a list of modified files that you cannot discard and don't want to commit. In that case, you can use this work-around to essentially make git forget that it wants to modify those files:

  1. Check out the old version
  2. Turn off end-of-line normalization
  3. git reset
  4. Re-enable end-of-line normalization
Community
  • 1
  • 1
Collin K
  • 15,277
  • 1
  • 27
  • 22
2

What you want is git reset HEAD --hard. git reset HEAD only un stages changes.

I suggest you also take a look at how git can be set to auto convert/deconvert line endings because on projects with multiple developers working on different platforms this will cause anger when a single edit on a file causes git blame to show you as having changed the whole file.

Community
  • 1
  • 1
Dan
  • 1,981
  • 1
  • 14
  • 18
  • I've tried both `git --config global core.autocrlf true` followed by `git reset HEAD --hard` and `git --config global core.autocrlf false` followed by the same command. Git still believes I have an uncommitted change in my working folder. I believe it is CR/LF-related, but I can't figure out how to solve it without checking in the file. – Nilzor Jan 24 '14 at 09:02
  • also check file permissions, I've had co-workers see file permission changes show up as a difference, but no actuall lines, if git diff doesn't show anything permissions may very well be the issue.. Also If you have both CR , LR, and CRLF in the file there could be issues no matter what option you pick. – Dan Jan 28 '14 at 14:15
1

I ran into something similar. My setup is using git on a web server to pull down the most recent code. For an unknown reason, it ran into this issue.

# git reset HEAD —hard

Unstaged changes after reset:

 'File Name'

I tried all the suggested things here. None fixed it.

I fix it in this case by doing

git add 'File Name'

then,

git reset --hard HEAD

Which cleared the issue for me.

Lahiru Jayaratne
  • 1,684
  • 4
  • 31
  • 35
zooppoop
  • 171
  • 1
  • 1
  • 9
0

"Why is it still listed as an unstaged change?"

Because bare git reset HEAD does not do anything to your working tree. It only resets the HEAD pointer to the commit you name (a no-op in this case, since you name HEAD), and resets the index to match the new HEAD (which, again, is the same in this case - so the net effect is basically only throwing away any git add, git rm, etc. commands you had done).

twalberg
  • 59,951
  • 11
  • 89
  • 84
0

I just got stuck in this situation and the only thing which fixed it was the following:

git log

Find the first commit in the repo and get the hash (in my case started with fdb14f)

Note: This only works because the repo with the issue was on a Linux server while I had a remote repo "origin" on my Windows box that contained the most recent commit which fixed the CRLF issue.

git reset --hard fdb14f
git pull origin master

After trying all kinds of different things this is what finally allowed me to get around the issue. I had fixed the CRLF issue in the most recent commit, but nothing else I tried would allow me to get around these files.

CaffeineConnoisseur
  • 3,635
  • 4
  • 19
  • 16