How to change the casing of a filename when using git on Windows

When you rename a file by changing its casing on Windows (ex: movie.cs -> Movie.cs), git will ignore the change. To change the casing, use the following git command:

git mv movie.cs Movie.cs
Code language: Bash (bash)

This will rename the movie.cs file to Movie.cs on the file system and in the git repository, resulting in a rename change, which you can then commit:

Changes to be committed: (use "git reset HEAD <file>..." to unstage) renamed: movie.cs -> Movie.cs
Code language: plaintext (plaintext)

This will work even if you manually changed the filename (like through Visual Studio). The important thing is it changes the filename in the git repository.

This behavior is controlled by the git core.ignorecase setting, which is true by default (at least on Windows). This is why it ignores filename casing changes.

Changing a directory’s casing

To change a directory’s casing (ex: /data/ -> /Data/), you have to do it in two steps:

git mv data tmp git mv tmp Data
Code language: Bash (bash)

This will result in all of the files in the directory having rename changes, which you can then commit:

Changes to be committed: (use "git reset HEAD <file>..." to unstage) renamed: data/MovieRepository.cs -> Data/MovieRepository.cs
Code language: plaintext (plaintext)

The history is retained for all of the renamed files, as you can see below:

Commit history in GitHub for files in a renamed directory

Setting core.ignorecase to false can lead to duplicate files

I wouldn’t suggest changing git to ignore filename casing by setting core.ignorecase=false. This can lead to problems, such as duplicate files.

Here’s an example of a mess this can cause.

Let’s say you want to rename Movie.cs to movie.cs and you notice that git isn’t seeing the file change. So you execute the following to have git pay attention to filename casing:

git config core.ignorecase false
Code language: Bash (bash)

The problem is git thinks this is a new file (notice it’s “Untracked”):

Untracked files: (use "git add <file>..." to include in what will be committed) movie.cs
Code language: plaintext (plaintext)

If you commit this, you’ll now have movie.cs and Movie.cs in the repository. Here’s what it’ll look like in GitHub:

GitHub showing movie.cs and Moviec.s

It will seem fine locally, because you’ll only see one file on the file system (Windows is case insensitive, so it’s impossible to have movie.cs and Movie.cs in the same directory). This can lead to big messes.

Delete duplicate file

Here’s one way to clean up the mess by deleting the duplicate file.

  • First, keep core.ignorecase=false for now. It caused the problem, but you’ll need to keep this setting as is while you clean up the mess.
  • Manually delete movie.cs from the file system.
  • Execute git status and make sure you see two deleted changes:
Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) deleted: Movie.cs deleted: movie.cs
Code language: plaintext (plaintext)
  • Commit and push the deleted change for the duplicate file (in this case, we want to delete Movie.cs):
git add Movie.cs git commit -m "Deleted duplicate" git push
Code language: Bash (bash)
  • Undo the deleted change for the remaining file:
git checkout -- movie.cs
Code language: Bash (bash)
  • Look at the repository in GitHub and notice the duplicate file (Movie.cs) was removed.
  • Now reset the core.ignorecase setting so git is case insensitive again (to prevent this mess from happening again):
git config core.ignorecase true
Code language: Bash (bash)

Leave a Comment