Skip to main content

git-mv-folder-renames

You're hitting a very common and frustrating issue when working with Git across case-sensitive (Linux) and case-insensitive (macOS, Windows) file systems. macOS, by default, is "case-preserving but case-insensitive," meaning it remembers the case you used when creating a file, but it treats file.txt and File.txt as the same file. Git, on the other hand, is case-sensitive by default.

Here's a breakdown of the problem and how to adjust your workflow and naming conventions:

Understanding the Problem

  • macOS and Windows: Your local file system sees folderName and Foldername as the same thing. So, if you rename folderName to Foldername directly in your file explorer, Git might not register it as a change, because the underlying OS still sees it as the "same" file.
  • Linux (and GitHub): Linux file systems are case-sensitive. If you push folderName to GitHub, and then someone on Linux tries to clone or pull changes where you've locally changed it to Foldername, it will cause conflicts or show two different folders. GitHub itself (which runs on Linux servers) will treat folderName and Foldername as distinct.

Solutions and Workflow Changes

1. Always use git mv for Renames

This is the most crucial and reliable solution. Instead of renaming folders directly in your operating system's file explorer, always use git mv in your terminal.

Example: If you have a folder named components and you want to rename it to Components:

git mv components Components
git commit -m "Rename components to Components for consistency"
git push

What this does: git mv tells Git explicitly that you are renaming a file/folder, even if only the case is changing. Git will then record this rename in its index and when you commit, it will be reflected correctly in the repository.

For case-only renames (e.g., folderName to foldername): Sometimes, git mv folderName foldername might not work directly on macOS due to the underlying filesystem. In this case, you can use a two-step rename:

git mv folderName tempFolderName # Rename to a temporary, distinct name
git mv tempFolderName foldername # Rename to the desired case
git commit -m "Rename folderName to foldername"
git push

This forces Git to see two distinct renames, which often bypasses the OS's case-insensitivity.

2. Configure core.ignorecase (Use with Caution)

Git has a configuration setting called core.ignorecase.

  • git config core.ignorecase true (Default on macOS/Windows): Git tries to be helpful by ignoring case differences in file names when comparing with the filesystem. This is why it doesn't always pick up case-only renames automatically.
  • git config core.ignorecase false (Default on Linux): Git treats file names as case-sensitive.

You can try setting core.ignorecase to false in your Git configuration:

For the current repository:

git config core.ignorecase false

Globally for all your Git repositories:

git config --global core.ignorecase false

Pros of setting core.ignorecase false:

  • Git will be more strict about case sensitivity, which can help align your local repo with how Linux/GitHub sees things.

Cons/Caveats of setting core.ignorecase false:

  • Does not override the OS: While Git will track case changes, your macOS filesystem still treats file.txt and File.txt as the same. This means you cannot have both file.txt and File.txt in the same directory on macOS, even with core.ignorecase false. If your codebase relies on having both (which is generally bad practice), this setting won't magically solve it.
  • Potential for local confusion: If you set core.ignorecase false and then perform a case-only rename outside of git mv, Git might tell you that you have two files (oldname and NewName) when your OS only shows one, leading to a confusing state.
  • Cross-platform consistency: While it helps Git track case changes, you still need to be careful when pulling changes from a Linux system that might have introduced a file with a case that conflicts with an existing file on your macOS system (e.g., if someone creates FOO/bar.js and you have foo/bar.js).

Recommendation: While git config core.ignorecase false can help, the git mv approach is generally safer and more universally recommended, as it directly manipulates Git's index rather than relying on filesystem-level workarounds.

3. Establish Strict Folder Naming Conventions

This is a best practice for any cross-platform development team, especially when dealing with case-sensitive issues.

  • All Lowercase (Kebab-case or Snake-case): This is the most robust and widely recommended convention.
    • Kebab-case: my-component-folder, user-profile-page (using hyphens)
    • Snake-case: my_component_folder, user_profile_page (using underscores)
    • Why: Eliminates all ambiguity related to case. If everything is lowercase, there's no way for case sensitivity to cause issues.
  • Avoid Spaces: Spaces in file/folder names can cause issues with command-line tools and scripts across different operating systems. Use hyphens or underscores instead.
  • Avoid Special Characters: Stick to alphanumeric characters, hyphens, and underscores. Characters like !@#\$%^&*() can cause unexpected problems.
  • Consistency is Key: Whatever convention you choose, apply it uniformly across your entire repository. This makes it easier for all developers to navigate and avoids introducing new case issues.

Examples for your tech stacks:

  • React Native/Angular/HTML:
    • src/components/button-primary/button-primary.tsx (kebab-case for folders and files)
    • src/pages/user-profile/user-profile.html
  • Node.js:
    • src/services/auth-service.js
    • src/routes/api-routes.js

4. Clean Up Existing Case Issues

If you already have inconsistencies, you'll need to fix them carefully.

  1. Backup: Before attempting any major renames, make sure your work is backed up or committed to a safe branch.
  2. Ensure all developers are on the same page: Communicate these changes to your team members so they know to pull the latest changes and update their local repositories.
  3. Use git mv (as described in point 1): Systematically rename problematic folders using the two-step git mv process if direct rename doesn't work.
  4. Force push (only if necessary and with caution): If you've corrected a significant number of case issues and have committed them, and you're confident that no one else has pushed conflicting changes, you might need to force push (git push --force-with-lease or git push -f). However, force pushing rewrites history and should only be done if you fully understand the implications and communicate it with your team. It can lead to data loss if not handled correctly. A safer approach is to ensure everyone pulls, addresses any conflicts, and then you push.

5. Consider a Case-Sensitive Filesystem (Advanced/Less Common for Most Devs)

For macOS users, it's possible to create a separate APFS volume that is case-sensitive. This is a more involved setup and might be overkill for most development workflows, but it completely eliminates the OS-level case-insensitivity. You would store your Git repositories on this case-sensitive volume.

Summary of Workflow Changes

  1. Adopt a consistent, lowercase (kebab-case or snake-case) naming convention for all files and folders.
  2. ALWAYS use git mv for renaming files and folders, especially for case-only changes. If a direct git mv fails, use the two-step temporary rename.
  3. Communicate these best practices with your team.

By consistently following these practices, especially using git mv and adopting a strict lowercase naming convention, you'll significantly reduce or eliminate folder naming issues when collaborating across different operating systems.