Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git status showing two files modified after rename due to case

Using git, I apparently didn't use the proper approach when renaming files based on case sensitive file names on my Mac.

Here is a simulation of the situation I'm in currently and am unsure how to get out of...

Create the repo and add a sample file:

git init
touch Foo.js
git add .
git commit -m 'adding Foo.js'

How I 'renamed' file (but should have used git mv... instead :( )

mv Foo.js foo.js
git status

Git status didn't show any changes so I updated the core.ignorecase property

git config core.ignorecase false
git status

Now it shows that I need to add foo.js.

git add foo.js
git status
git commit -m 'renaming Foo.js to foo.js'

Now if I try to edit foo.js

vim foo.js <-- edit foo.js
git status

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:   Foo.js
    modified:   foo.js

If I try to git rm Foo.js it also is trying to delete my foo.js file as well.

My current git --version is 2.1.2

Any thoughts on how I fix things so Foo.js is gone and I only have foo.js?

like image 890
Jason Jarrett Avatar asked Nov 24 '14 19:11

Jason Jarrett


People also ask

What happens if you rename a file in Git?

Git keeps track of changes to files in the working directory of a repository by their name. When you move or rename a file, Git doesn't see that a file was moved; it sees that there's a file with a new filename, and the file with the old filename was deleted (even if the contents remain the same).

Is Git case sensitive for file names?

The Windows and macOS file systems are case-insensitive (but case-preserving) by default. Most Linux filesystems are case-sensitive. Git was built originally to be the Linux kernel's version control system, so unsurprisingly, it's case-sensitive.

How does Git know a file has been renamed?

So to detect renames is a matter of comparing hashes. To detect small changes to a renamed file, Git uses certain algorithms and a threshold limit to see if this is a rename. For example, have a look at the -M flag for git diff . There are also configuration values such as merge.

What is modified files in Git?

As you edit files, Git sees them as modified, because you've changed them since your last commit. As you work, you selectively stage these modified files and then commit all those staged changes, and the cycle repeats.


2 Answers

Use 'git revert' on that commit where you included the renamed version of the file. Then you can [properly] rename the file - as you indicated in your description - and create a new commit.

Example of properly renaming the file:

git mv --force Foo.js foo.js
like image 143
Thom Parkin Avatar answered Oct 18 '22 19:10

Thom Parkin


Git 2.29 (Q4 2020) adds another way to deal with this case:

See commit 087c616, commit 409f066, commit 5065ce4 (20 Sep 2020) by brian m. carlson (bk2204).
(Merged by Junio C Hamano -- gitster -- in commit c5a8f1e, 29 Sep 2020)

docs: explain how to deal with files that are always modified

Signed-off-by: brian m. carlson

Users frequently have problems where two filenames differ only in case, causing one of those files to show up consistently as being modified. Let's add a FAQ entry that explains how to deal with that.

In addition, let's explain another common case where files are consistently modified, which is when files using a smudge or clean filter have not been run through that filter.
Explain the way to fix this as well.

gitfaq now includes in its man page:

Why do I have a file that's always modified?

Internally, Git always stores file names as sequences of bytes and doesn't perform any encoding or case folding.

However, Windows and macOS by default both perform case folding on file names.
As a result, it's possible to end up with multiple files or directories whose names differ only in case.

Git can handle this just fine, but the file system can store only one of these files, so when Git reads the other file to see its contents, it looks modified.

It's best to remove one of the files such that you only have one file. You can do this with commands like the following (assuming two files AFile.txt and afile.txt) on an otherwise clean working tree:

$ git rm --cached AFile.txt
$ git commit -m 'Remove files conflicting in case'
$ git checkout .

This avoids touching the disk, but removes the additional file.
Your project may prefer to adopt a naming convention, such as all-lowercase names, to avoid this problem from occurring again; such a convention can be checked using a pre-receive hook or as part of a continuous integration (CI) system.

It is also possible for perpetually modified files to occur on any platform if a smudge or clean filter is in use on your system but a file was previously committed without running the smudge or clean filter.
To fix this, run the following on an otherwise clean working tree:

$ git add --renormalize .
like image 29
VonC Avatar answered Oct 18 '22 20:10

VonC