# Vim Line Ending Issues

You open a file and see ^M at the end of every line, or Git complains about line endings. These issues stem from different line ending conventions across operating systems. Let me show you how to fix them.

Understanding Line Endings

Different operating systems use different characters for line endings:

SystemCharactersHexDisplay
Unix/Linux/macOSLF0x0A\n
WindowsCRLF0x0D 0x0A\r\n
Old Mac (pre-OS X)CR0x0D\r

Check Current File Format

Vim calls line endings "fileformat". Check the current setting:

vim
:set fileformat?

Returns unix, dos, or mac.

You can also see both the fileformat and encoding:

vim
:set ff?

Viewing ^M Characters

When you see ^M in Vim, those are carriage return characters (\r). They appear when a file with Windows line endings is opened as Unix format.

To see them explicitly:

vim
:set list

This shows all special characters. $ marks line endings, and ^M shows carriage returns.

Hide them again:

vim
:set nolist

Convert Line Endings

Convert Windows (CRLF) to Unix (LF)

vim
:set fileformat=unix
:w

Or use the abbreviated form:

vim
:set ff=unix
:w

Convert Unix (LF) to Windows (CRLF)

vim
:set fileformat=dos
:w

Convert to Mac (CR only - rarely needed now)

vim
:set fileformat=mac
:w

Remove ^M Characters Manually

If the conversion doesn't work, remove them manually:

vim
" Substitute all ^M characters
:%s/\r//g

Note: Type ^M as Ctrl-V Ctrl-M, not as the literal characters ^ and M.

Or using the escape sequence:

vim
:%s/\r\+$//g

Force File Format on Open

Open a file with a specific format:

```vim " Open as Unix format :e ++ff=unix

" Open as DOS format :e ++ff=dos ```

This tells Vim how to interpret line endings regardless of detection.

Automatic Detection

Vim tries to detect the file format. Check what formats it considers:

vim
:set fileformats?

Default is usually unix,dos. This means Vim tries Unix first, then DOS.

For better detection, set:

vim
set fileformats=unix,dos,mac

Git and Line Endings

Git has its own line ending handling. Configure .gitattributes:

``` # Auto-detect text files and normalize to LF * text=auto

# Files to always have LF *.sh text eol=lf *.py text eol=lf

# Files to always have CRLF *.bat text eol=crlf *.cmd text eol=crlf ```

In Git config:

```bash # Normalize to LF on commit, checkout as-is git config --global core.autocrlf input

# On Windows, checkout as CRLF, commit as LF git config --global core.autocrlf true ```

Batch Conversion from Shell

Convert multiple files:

```bash # Using dos2unix (install first) dos2unix *.txt

# Using sed sed -i 's/\r$//' *.txt

# Using tr tr -d '\r' < input.txt > output.txt ```

Preserve File Format

To keep the original file format when editing:

vim
" Preserve file format
set preserveindent

Mixed Line Endings

Sometimes a file has mixed line endings. Find them:

```vim " Search for CR characters /\r

" Or show fileformat on each line :%!cat -A ```

Fix mixed endings by converting:

vim
:set ff=unix
:w

Modeline for File Format

Add a modeline to files to ensure consistent handling:

python
# vim: set fileformat=unix :

Or in comments:

html
<!-- vim: set fileformat=dos: -->

Script to Fix Line Endings

Add this to your .vimrc:

```vim function! FixLineEndings() let l:ff = &fileformat if l:ff == 'dos' set fileformat=unix write echo 'Converted to Unix line endings' endif endfunction

command! FixLines call FixLineEndings() ```

Automatic Fix on Save

Auto-convert to Unix format for specific files:

vim
autocmd BufWritePre *.sh,*.py,*.c,*.h set ff=unix

Display Line Ending Info in Status Line

Show file format in your status line:

vim
set statusline=%<%f\ %h%m%r%=%y%{&ff}\ %-14.(%l,%c%V%)\ %P

The %{&ff} shows the current file format.

Troubleshooting Common Issues

Git Shows File as Modified but No Changes

This is usually line ending conversion. View the actual changes:

bash
git diff -w  # Ignore whitespace
git diff --ignore-cr-at-eol

File Appears as One Long Line

The file might have Mac (CR only) line endings:

vim
:e ++ff=mac
:set ff=unix
:w

Scripts Fail with /bin/bash^M: bad interpreter

The script has Windows line endings. Convert it:

vim
:set ff=unix
:w

Or from command line:

bash
dos2unix script.sh

Vim Changes Line Endings on Save

Vim preserves format by default. If it's changing, check:

vim
:set fileformat?
:set fileformats?

Make sure the format is detected correctly before saving.

Quick Reference

```vim " Check current format :set ff?

" Convert to Unix :set ff=unix

" Convert to Windows :set ff=dos

" Open with specific format :e ++ff=unix

" Remove ^M characters :%s/\r//g

" Show special characters :set list

" Hide special characters :set nolist ```

Line ending issues are straightforward once you understand the file format settings. The key is knowing how to check, convert, and prevent them in the future.