Git Status Ignore Line Endings/Identical Files/Windows & Linux Environment/Dropbox/Meld

Is there a way in GIT, to remove files changed from being committed if it has less than 2 characters changed?

I think it is more likely that these files are showing up due to mode changes. Try running git diff on one of them. Do you see something like this?

$ git diff query.viewport.js
diff --git a/query.viewport.js b/query.viewport.js
old mode 100644
new mode 100755

If so, then you might be able to solve this with something like:

$ find modules/hotsite/ -type f -print0 | xargs -0 chmod -x

Why is git showing line endings change although there should be none?

What's going on here is this:

  • The committed file (which cannot be changed) actually has CRLF endings.
  • The index copy, once you run git add, will not have CRLF endings: it will have LF-only endings. (It currently has CRLF endings, based on the git ls-files --eol output, which makes sense as the initial index copy is made by reading the committed copy into the index. This keeps the committed copy's CRLF endings intact. But eol=crlf in .gitattributes says that when you run git add, Git should strip the carriage returns, so it will do that.)
  • A future commit will be made from what is (in the future) in the index: that is, what would be in the index if you run git add.
  • Therefore the diff between what's committed now, and what would be committed next if you ran git add and git commit, involves removing all the carriage returns from the file that would be git added once you run git add.

Basically, any time you change the "normalization" process for some file(s)—the way that Git will convert that file or those files from the committed copies to the working tree copies, or vice versa—you may need to make one new "convert the file(s)" commit first. That way you'll have the new normalization in effect. You can then make changes the usual way, and these changes will be normalized in accordance with the new normal.

To make those newly normalized copies, consider using git add --renormalize, if your Git is not too ancient (very old Git versions lack the --renormalize option and you must trick such a Git into re-adding the file). Do this before making any other changes, and make a new commit that has, as its commit message, something that will remind you why you made this commit. For instance:

renormalize files

We changed the `.gitattributes` setting, so we now need to
renormalize files. Git will show every line changed in
this commit, and `git blame` will point to this commit; use
Git's facilities for skipping over this commit when using
`git blame` because although every line *is* changed, these
changes are purely white-space housekeeping changes that are
not otherwise noteworthy.

Now that you have made this new commit so that the committed files match the new normal, you can go back to working as usual. If you later are looking for something of interest and run git blame and discover this commit and its error message, it will remind you to look up the git blame documentation and see how to tell git blame don't count the renormalization commit. (See the --ginore-rev and --ignore-revs-file options.)

Unable to checkin linux format file from windows

You don't need to do anything.

The explanation is a little tricky though. You need to be aware that when you use Git, there are always three version of each active file.

The reason that two of these versions exist is obvious enough with a bit of thought. The third one is a bit odd; we'll get to that in a moment.

Start with the fact that each commit, as identified by its unique hash ID, stores a full snapshot of all of your files. This inside-a-commit snapshot stores the files in a special, read-only, Git-only format. Only Git can actually use these files. The special Git format causes de-duplication, so if you have the same versions of some file(s) in multiple commits, there's really only one copy of that file. That's why it's not a big deal that every commit has a full copy of every file: they're all shared whenever possible. Since each file is frozen for all time, it's easy to share it.

But because these copies of files literally can't be changed, and can't be used by any other non-Git program on your computer, they are no good for doing work. They are only useful as archived commits. So when you use git checkout (or git switch in Git 2.23 or later), you pick one commit that you'd like to have "checked out". Git copies all of the files from that commit, turning them from special, read-only, Git-only frozen files into regular everyday read/write files, in your computer's normal file format.

The copies that Git puts into normal everyday format, that you can see and work with, are in a work-space area. Git calls this your working tree or work-tree. Since these are ordinary files, you can use them, and even change them whenever you like.

So that's why there are two copies of each file in use: there's the frozen one in the current commit, and there's the normal-format one in your work-tree. But what about that third copy? This copy is in what Git calls its index, or the staging area (two terms for the same thing). This one sort of sits in between the frozen HEAD-commit copy, and the work-tree copy.

Let's draw a simple illustration of the three copies, assuming you have just two files named README.md and main.py:

   HEAD         index       work-tree
--------- --------- ---------
README.md README.md README.md
main.py main.py main.py

All three copies of, say, main.py match—well, sort of—at the beginning, right after your initial git checkout. The HEAD one, the one in the current commit, is frozen: it literally cannot be changed. The work-tree copy is yours to do with as you like.

The one in between is the one that Git will put in the next commit you make. Right now, it matches the other two. But what if you change main.py? Let's add a version-number to each file:

   HEAD         index       work-tree
--------- --------- ---------
README.md(1) README.md(1) README.md(1)
main.py(1) main.py(1) main.py(2)

You changed the work-tree copy, so we bumped the version number. (It's not actually in the file, we're just drawing it to keep track of what each copy looks like.)

If you want your changed main.py to go into your next commit, you must now run git add main.py. This copies the main.py file into Git's index, replacing the existing one. The new copy is in Git's frozen format, but isn't actually frozen yet:

   HEAD         index       work-tree
--------- --------- ---------
README.md(1) README.md(1) README.md(1)
main.py(1) main.py(2) main.py(2)

... but now, after git add, the copy in the index is different from the HEAD copy (and is the same as the work-tree copy). If you run git commit now, Git will make a new frozen commit from the index copies of each file.

Notice that the copies are index → work-tree and work-tree → index

When Git extracts the commit initially, it needs the frozen-format files in its index. That's easy and is a straight copy.1 Git needs to copy that frozen-format file to your work-tree, though, and this involves de-compressing and de-Git-izing it. Git makes this copy by extracting the index version (frozen-format) to your work-tree (a regular everyday file):

  • index → work-tree: de-compress

Meanwhile, your later git add has to copy your work-tree file into the index:

  • work-tree → index: compress into frozen format

What if, while Git is doing these copies, we gave Git the ability to turn Unix / Linux style LF-only line endings into Windows-style CRLF line endings? Then we just need this:

  • index → work-tree: de-compress and Windows-ify
  • work-tree → index: de-Windows-ify and re-compress

and that's what Git does, when you tell it to manipulate line endings.


1Actually, it's even easier, because the index doesn't hold a true copy of the file, but rather a reference to an internal Git blob object. But you don't need to worry about this—not unless you get down into the details of using git ls-files --stage and git update-index, anyway.


What you did

You started out, and ran for some number of commits so far, with core.autocrlf set to true. This tells Git: do mess with my line endings. The files Git modifies are, by default, the ones it guesses are the right ones to have this done to them. (It's usually wiser to use .gitattributes to tell Git which files should be manipulated like this, rather than letting Git guess, but Git's guesses are pretty good, most of the time.)

Since Git already does the same de-Windows-line-ending work, the earlier files, committed on Windows, already have Linux-style LF-only line endings. The index copies, which always literally match the committed copies initially, also have Linux-style LF-only line endings.

Only your work-tree copies have other kinds of line endings and even then, they only have those line endings if you told Git to manipulate line endings (which you did).

When you tell Git don't mess with my line endings at all, then it matters whether your work-tree files have CRLF line endings, or LF-only line endings, because then git add will copy whatever you have in your work-tree, into Git's index, without messing with any line endings. Setting core.autocrlf to false, and not having any more-explicit settings in .gitattributes, does this, so now it becomes important to make sure your work-tree files have the endings you want to have in new copies you git add and then git commit.

You ran dos2unix on two work-tree files. This takes their CR-LF Windows-style line endings, if they had those line endings in the first place (they probably did), and turns them into LF-ony line endings. Then you ran git add. The git add step this time didn't de-Windows-ize the line endings, but did re-compress the files. The result was ... the same file that was already in the index, for each file, because the index copies have been Unix / Linux style all along.

Note that it's now very important what line endings you put in each file, because with core.autocrlf turned off, and no .gitattributes entries, you've told Git: hands off all file contents: do not mess with line endings.

If you'd like Git to mess with line endings in a really predictable fashion, rather than guessing, you should create a .gitattributes file and list each file name or file-name-pattern and the correct treatment for that file. This is a bit painful to set up initially, but after that, tends to work well—it's what the Git folks do with the Git project.

Git Line Endings problem on a Windows shared volume with a Unix docker container

The way to configure line endings is:

On Linux:

git config --global core.autocrlf input

On Windows:

git config --global core.autocrlf true

You can also set repository-specific configurations:

cd /path/to/repo
git config core.autocrtlf <value>

In your situation, it sounds that if you set git config --global core.autocrlf input in your CentOS containers and git config --global core.autocrlf true for your Windows machine, you shouldn't have issues.

Ubuntu subsystem on Windows - changes line endings even though I've defined the core.autocrlf to true

The only thing you would read from me is: "What is the correct core.autocrlf setting I should use?"

Meaning:

git config --global core.autocrlf false

Then, as mentioned in "Disable git EOL Conversions":

git add --renormalize .

Using .gitattributes core.eol directive is the right approach to fix eol.

And you can check what is applied to which file with:

git ls-files --eol

Git pull on Windows (git smc client) doesn't respect .gitattributes's eol=lf

Regarding eol conversion:

  1. Make sure core.autocrlf is set to false (that way, only [.gitattributes directives]1 will be in play)
  2. Use text eol=lf
  3. Follows by git add --renormalize . to force the application of the .gitattributes directives. (since Git 2.16, Q1 2018)

after removing the index via rm .git/index and performing git reset --hard HEAD, the problem was gone

That is what git add --renormalize . is supposed to emulate.



Related Topics



Leave a reply



Submit