Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git line endings - can't stash, reset and now can't rebase over spurious line endings commit

I have a repo I added a gitattributes to it and was working on it fine. I sync it via dropbox to another machine. When I opened it to the other machine a bunch of files suddenly appeared on the unstaged area as total diffs (all the file a huge diff which means line endings diff) - my crlf endings are basically .* text=auto and I am working on windows. I tried to stash the changes, reset the branch etc. At long last I decided to commit the files and then made some other commits I wanted to reorder (and squash) before the line endings commit. When I try rebasing I get a :

error: Your local changes to the following files would be overwritten by merge
        # those same files
Please, commit your changes or stash them before you can merge.
Aborting
Could not apply 89b25b81fff1a1e7893319e123aaaca9c4162a95... <commit message>

Of course stash does not work

Is it a bug ?

Related:

  • How do I fix line ending issues after migrating from SVN to git? (yes mine is a git-svn clone, but I do not think it is really important)
  • Can't seem to discard changes in Git (yep and I want to know why)
  • git thinks files have changed
  • Can someone explain to me what difference git diff is seeing here?

EDIT Nothing to do with machines - on the same machine some (...) operations just make those files (they are on the .gitattributes as text) appear in the "changed" section. The only workaround that seems to exist is:

git rm --cached -r .
git reset --hard

USE CAREFULLY

EDIT: hack above moved to alias status:

[alias]
     crlf = !git rm -r . --cached -q && git reset --hard

UPDATE 2015.09.30: I have a git repo in an NTFS partition I use from windows 7 and arch linux in a dual boot environment. When I shut windows down and I boot into arch two files (html) show as total diffs (line ending diffs). The above workaround does not work - unless you apply it several times refreshing the gui in between...

My .gitattributes:

* text=auto

*.py text diff=python
*.html text
.project text
*.pkl -text

# M$ files
*.bat text eol=crlf

# UNIX files
**/generate_second_post text eol=lf

# git files - have them with LF, as I edit them via the shell (echo etc)
*.gitignore text eol=lf
*.gitattributes text eol=lf

NB: linux will let me commit, switch branches etc but won't let me rebase - plus those diffs always appear in gitk/git gui.

2018/12/14 moved to mac and my workaround does not work anymore. I posted a message to the git mailing list: https://marc.info/?l=git&m=154482149623324&w=2

Let's hope this will get some attention

$ git --version
git version 2.19.2
like image 807
Mr_and_Mrs_D Avatar asked Jan 14 '14 19:01

Mr_and_Mrs_D


People also ask

How do I fix git line endings?

fix-git-line-endings #Set LF as your line ending default. #Save your current files in Git, so that none of your work is lost. #Remove the index and force Git to rescan the working directory. #Rewrite the Git index to pick up all the new line endings.

Does git Preserve line endings?

text eol=crlf Git will always convert line endings to CRLF on checkout. You should use this for files that must keep CRLF endings, even on OSX or Linux. text eol=lf Git will always convert line endings to LF on checkout. You should use this for files that must keep LF endings, even on Windows.

Should I use CRLF or LF?

Whereas Windows follows the original convention of a carriage return plus a line feed ( CRLF ) for line endings, operating systems like Linux and Mac use only the line feed ( LF ) character. The history of these two control characters dates back to the era of the typewriter.

How does git store line endings?

Git store whole files as "blobs" and only do conversion when reading (checking out) or writing (indexing). Git does not store "neutralized lines". So yes, Git can save files with mixed line endings, but that's usually a bad practice to avoid. So, this means, checkout a file with Line Ending A (= .


2 Answers

Finally after 5 years here is a complete answer, thanks to Torsten Bögershausen.

The way to debug this eol situation is to investigate using the --eol switch to git ls-files added by Torsten Bögershausen. Turns out that the file(s) in question were committed with CRLF while the .gitattributes file added later specified text for these files. This results in an "illegal state". Nothing to be done, for old commits.

What should be done is git add --renormalize . so the files are added with correct (lf) line endings and then reset --hard to have those lineendings in the working tree.

Now this won't help with old commits, however (the commits that are in this illegal state, so between the files were committed with wrong line endings and the gitattributes commit) - checking those out will probably lead to those unresetable changes. The fix for this is provided by the answer by @iKlsR:

$ cat .git/info/attributes
"Mopy/Docs/Bash Readme Template.html" -text

the reason being that:

When deciding what attributes are assigned to a path, Git consults $GIT_DIR/info/attributes file (which has the highest precedence), .gitattributes file in the same directory as the path in question, and its parent directories up to the toplevel of the work tree [ect]

(emphasis mine)

Just be sure to add the line after you renormalise, otherwise the file(s) won't be added to the renormalise commit!

like image 194
Mr_and_Mrs_D Avatar answered Oct 10 '22 18:10

Mr_and_Mrs_D


We ran into this issue today where it seemed the problem stemmed from some CRLF-related issues related to a newly added .gitattributes file with a single line * text=auto. When you rebased or created a new branch, said file would follow you and ruin any changes that came after along with preventing you from leaving that branch without first committing it.

We initially fixed this by checking out a temporary branch, reverting the file back to a sane state (before modifications), committing and then doing a rebase on the entire branch back to the oldest commit to make it look like master. That worked for a while but a similar file popped up after that and the same fix didn't work again.

What we eventually went with was similar to what op shared in his update.. a single line inside .git/info/attributes with file-to-remove -text seems to mitigate the problem. I say mitigate because I'm not sure if there are any adverse implications to doing this, this was also for one file so might not work as well if at all.

like image 4
iKlsR Avatar answered Oct 10 '22 19:10

iKlsR