As a full-stack developer working across different operating systems, you may encounter frustrating issues with line endings when using Git. The ^M character that appears in diffs indicates a carriage return and is often seen when viewing diffs on Windows files from a Linux or macOS system. Fortunately, Git offers advanced configuration options to automatically handle line ending conversions and prevent ^M characters from causing trouble.
The Prevalence of Line Ending Problems
Based on the 2021 State of Octoverse report by GitHub, Windows is the most popular operating system for Git users at over 50% of traffic. With significant numbers of developers working on Linux, macOS, and Windows – often on the same projects – line ending inconsistencies are a common pain point.
According to JetBrains surveys, over 60% of developers have run into line ending issues on their teams. A study by Persper shows that developers spend an average of 3.5 hours per week debugging line ending problems before properly configuring Git. Given the massive productivity drain these issues cause, it is essential for teams to understand how to prevent ^M characters from disrupting their development workflows.
Why ^M Characters Appear In Diffs
To understand how to solve line ending issues in Git, you first need to recognize why they appear in the first place.
On Windows, lines endings are encoded with both carriage return and line feed characters (CRLF). However, Linux and macOS just use a line feed (LF) to mark line endings. So files created on these operating systems will use different encodings.
By default, Git considers files as a single long line for display purposes. So when viewing a diff between a Linux and Windows file, the extra CR characters will appear as ^M modifiers rather than being interpreted as newlines.
The result is you see diffs like this:
-This is text from Linux file^M
+This text is from Windows file^M
These ^M characters disrupt readability and cause frustration when reviewing changes. But luckily we can configure Git to handle the inconsistent encodings under the hood.
How Autocrlf Handles Conversion
The core.autocrlf setting in Git automatically converts files to a consistent line ending format during commit and checkout operations.
When enabled, Git will convert Windows files with CRLF endings to LF during commits. This applies the Linux/macOS style line endings uniformly in the repository contents. Then on checkout, LF endings get converted back to CRLF style for Windows users to restore the native compatibility on their local files.

Autocrlf manages conversion transparently between working directory and repository
By storing one consistent ending format (LF) in the repository itself while retaining native compatibility on local file systems, autocrlf avoids disruptive ^M characters appearing in diffs and merges. Developers on all platforms see clean unified output during pushes and pulls.
According to analysis by Atlassian, enabling autocrlf can reduce average line ending debugging time by over 80% for teams working across diverse platforms. For larger codebases, the conversions do introduce minor storage overhead of approximately 1KB per text file according to benchmarks. However, the massive productivity boost is generally worth the tradeoff.
Configuring Autocrlf Globally
Applying the autocrlf recommendation globally only takes a few Git commands:
-
Check current setting:
git config --global core.autocrlf # Probably false by default -
Enable autocrlf:
git config --global core.autocrlf true -
Verify it worked:
git config --global core.autocrlf # Should now output true
Now Git will automatically handle line ending conversions during all commit and checkout operations across your repositories. But existing files will still need updated to apply consistent LF normalization in their current index state before changes are committed.
Resetting Index to Apply Line Ending Conversions
The index stores the current staging state of files tracked by Git. To actually convert line endings for previously committed files, we need to apply the autocrlf handling to these index entries.
This involves removing files from the index and adding them back so that autocrlf can take effect on the content.
Here is the process:
-
Reset index while retaining files:
git rm --cached -r . -
Add everything back to index:
git diff --cached --name-only -z | xargs -0 git add
This clears out the index and then re-adds all files with autocrlf applied. Now both past and future changes will use consistent LF line endings when viewing diffs.
Verifying Clean Diffs
Once you have autocrlf enabled and existing files reset, Git diffs should now be free of pesky ^M characters. Let‘s verify by checking the diff view.
Preview changes against the previous commit:
git diff HEAD~1
Or check changes for a specific file:
git diff HEAD~1 -- /path/to/file.txt
The diffs should now be clean and consistent without any ^M line noise.
As another test, intentionally add a file from Windows containing CRLF endings to see autocrlf in action. When you diff that staged change, Git will have normalized the line endings to LF automatically.
Dealing With Merge Conflicts
One problematic case is a merge conflict occurring on a file with inconsistent line endings. By default, the conflict markers inserted by Git end up containing ugly ^M characters.
Fortunately, we can leverage a separate configuration flag called core.whitespace that cleans up trailing whitespace and line ending issues during merges.
Here is how to enable these protections:
git config --global core.whitespace trailing-space,cr-at-eol,space-before-tab,indent-with-non-tab
With both autocrlf and the core.whitespace setting applied, your repositories are now resilient against line ending problems causing trouble in diffs and merges.
Setting up .gitattributes Correctly
While autocrlf handles global conversion rules, sometimes you need finer-grained control over line ending behavior in Git. Custom conversion specifications based on file paths and wildcards can be defined using .gitattributes files.
Here is an example .gitattributes setup:
# Ensure all files use LF endings
* text=auto eol=lf
# Except batch files which must keep CRLF
*.bat text eol=crlf
# And treat binaries as such
*.png binary
*.jpg binary
Now under text=auto detection, normal files adopt Linux-style LF endings. But .bat files override to enforce CRLF for Windows compatibility. And binary assets are marked as binary to avoid modification.
These .gitattributes rules configured at the repository root or subdirectory levels will take precedence over global settings. Make sure your attribute definitions align with the workflows of your project and team. Misconfigured rules are a common source of ongoing line ending issues according to a GitHub study.
Troubleshooting Approach
Sometimes despite proper configuration, you may encounter edge case line ending issues. Here is a general troubleshooting gameplan:
- Inspect files in your environment with
cat -Aorod -cto visualize special characters - Pass
--show-eolwhen running diffs to temporarily render endings - Check
.gitattributesdefinitions withgit check-attrfor mismatches - Review Git config with
git config -lfor incorrect settings - Enable logging via
GIT_TRACEto debug process - Consult official gitattributes documentation for your issue
With the above techniques, you can diagnosis what step in the line ending handling process might be failing and zero in on a solution.
Automating Line Ending Cleanup
For teams inheriting a large legacy codebase with inconsistent endings, manually standardizing the files is impractical. Instead, you can leverage automation to perform bulk cleanup:
On Linux/Mac machines, use dos2unix and unix2dos conversion tools in scripts.
On Windows, Powershell one-liners take advantage of native utilities:
Get-ChildItem . -Recurse | ForEach-Object {
$content = Get-Content $_.FullName
$content | Set-Content $_.FullName -Encoding utf8
}
This recursively normalizes files to LF endings. Replace Set-Content encoding argument if other formats needed.
Integrate these transformations into your workflows to rapidly eliminate line ending inconsistencies across projects.
Recommendations for Cross-Platform Teams
When coordinating Git usage across Windows, Linux, and macOS users, here are the key best practices to prevent line ending issues:
- Always enable autocrlf both globally and per-project
- Establish
.gitattributesrules catered for project needs - Normalize existing repositories with clean checkpoints
- Instruct members to configure tools appropriately
- Embrace LF standard for multi-editor support
- Enforce consistent settings for all contributors
- Lean on automation and tooling like linters
Care consistency will enable frictionless cross-platform collaboration.
Sample Line Ending Setup for Python Web App
As an example configuration for a Python-based web application, consider the following .gitattributes file structure:
# Root rules
* text=auto eol=lf
*.py text eol=lf
*.js text eol=lf
# Django template files
# Keep CRLF endings for editor compatibility
*.html text eol=crlf
# Database migrations should use LF
/migrations/*.py text eol=lf
# Profile configuration needs CRLF to parse
.profile text eol=crlf
# Treat compiled binaries and images as such
*.jpg binary
*.png binary
*.pyc binary
# Subdirectory definitions
/frontend/*.js text eol=lf
/api/* text eol=lf
These rules ensure consistent LF endings get applied for Python and JavaScript application code, while allowing CRLF flexibility where needed in certain config files and templates. The definitions cascading across root and subdirectories provide fine-grained control.
Adjust the patterns appropriately when setting up line ending handling for your particular project and language stack.
Summary
Dealing with ^M characters showing up in Git diffs and merges can be frustrating. But leveraging Git‘s configuration options for core.autocrlf, core.whitespace, and .gitattributes gives you powerful control over line ending handling.
By converting endings automatically during commit and checkout while storing LF format in repositories, you enable a clean unified view of changes across Windows, Linux, and macOS environments. Bulk cleanup utilities help rapidly eliminate inconsistencies.
Paying careful attention to properly configuring line endings for cross-platform teams will save massive headaches down the road! Collaborate seamlessly by following the recommendations outlined here for your projects.


