CRLF vs LF en Windows: convertir, configurar y evitar líos en proyectos

Última actualización: 04/09/2025
Autor: Isaac
  • LF (Unix) y CRLF (Windows) son finales de línea distintos; homogeneízalos para evitar diffs y errores.
  • Git resuelve el problema con core.autocrlf y .gitattributes; usa * text=auto y reglas puntuales.
  • Configura el editor (VS Code/Visual Studio) y, si es necesario, renormaliza con git add --renormalize .
  • Mantén LF en el repositorio y deja a Windows usar CRLF en la copia de trabajo cuando convenga.

Convertir entre formatos de salto de línea en Windows

Si trabajas en Windows y alternas proyectos con gente de Linux o macOS, tarde o temprano te topas con la eterna batalla CRLF vs LF. A veces parece magia negra: editas un archivo, no cambias nada “visible” y Git marca medio fichero como modificado. Tranquilo, no es brujería; son los finales de línea jugando en tu contra.

Para ahorrarte dolores de cabeza, conviene entender qué hay debajo y cómo ajustar Git, tus editores y tus herramientas para que cada archivo llegue “limpio” al repositorio, sin cambios fantasma ni errores raros en CI/CD o scripts. En esta guía te cuento, con detalle y al grano, cómo convertir, configurar y normalizar CRLF y LF en Windows sin perder el tiempo.

Qué son LF y CRLF y por qué importan

Los finales de línea son caracteres de control que delimitan cada línea en un archivo de texto: LF (\n, ASCII 10) y CRLF (\r\n, ASCII 13+10). En sistemas tipo Unix (Linux, macOS) se usa LF, mientras que Windows utiliza CRLF por herencia de las impresoras y máquinas de escribir: primero retorno de carro (CR), luego avance de línea (LF).

La elección no es estética: cambiar de un formato a otro puede provocar diffs artificiales, scripts que fallan con “command not found”, pipelines que revientan al ejecutar en Linux archivos guardados con CRLF, o editores que muestran todo en una sola línea. Sí, abres un .sh con CRLF en Bash y te puedes comer un buen susto.

Para redondear, Unicode reconoce más separadores (NEL U+0085, LS U+2028, PS U+2029, VT U+000B, FF U+000C), pero en el desarrollo cotidiano el duelo real es CRLF vs LF. Aun así, saber que existen ayuda cuando te topas con textos de mainframes o ficheros raros que un editor antiguo no interpreta bien.

Otra curiosidad técnica útil: un salto puede tratarse como separador (entre líneas) o como terminador (marca el fin). Esa sutileza explica por qué a veces ves una última línea “sin salto final” o líneas vacías de más cuando mezclas herramientas. Si necesitas aprender a encontrar y reemplazar saltos de párrafo, ojo, porque algunos analizadores esperan una cosa u otra.

CRLF y LF diferencias por sistema operativo

Diferencias por sistema y problemas típicos

En Windows, lo normal es CRLF; en Linux y macOS, LF. Ese choque se nota enseguida en equipo mixto: alguien edita un archivo con su sistema, lo guarda, y el diff se llena de cambios que en realidad son solo finales de línea. A nivel práctico, te complica las revisiones y contamina el historial.

También hay efectos colaterales: un script con CRLF ejecutado en un entorno Unix puede fallar con errores crípticos, o en CI una tarea se rompe porque un shell interpreta mal los retornos. En el otro sentido, abrir en Windows un fichero con solo LF en editores antiguos puede aplanarlo en una línea.

Ojo con herramientas de integración continua como Jenkins o GitHub Actions: si la build corre en Linux pero tú subes archivos con finales de línea inconsistentes, puedes romper el pipeline aunque “todo funcione en mi máquina”. Más de uno ha perdido horas por esto.

La buena noticia es que hay una receta clara: fijar una convención y hacer que las herramientas la apliquen solas. Eso pasa por Git y por tu editor. Y si el mal ya está hecho, por renormalizar el repo.

  ¿Cómo se personaliza Windows 10 mientras no está activado?

Por cierto, editores modernos como VS Code muestran el tipo de salto en la barra de estado y permiten cambiarlo al vuelo; es un salvavidas cuando detectas archivos “cruzados” y quieres poner orden rápido, o cuando necesitas evitar saltos de página y formatos inesperados al pegar texto en documentos.

Configurar Git para CRLF y LF

Git y los finales de línea: core.autocrlf y .gitattributes

Git puede convertir finales de línea automáticamente para mantener el historial limpio y evitar sustos. La clave es la opción core.autocrlf, que debes entender bien antes de tocarla, y saber que la configuración puede estar a nivel global o local de repositorio (la local manda).

Revisa tu configuración global con –global y recuerda que en el repo puede haber otro valor distinto que es el que prevalece. Para consultar todo a nivel global, usa git config –list –global. Si en el repo ves comportamientos raros, comprueba el valor local y priorízalo según lo que necesites.

Modos de core.autocrlf en términos prácticos (Windows vs Unix): true convierte a CRLF al hacer checkout y vuelve a LF al commit; input solo convierte a LF al hacer commit (ideal en Linux/macOS); false no toca nada (y suele ser pan para hoy y hambre para mañana si hay equipo mixto). En Windows, lo más sensato es true si no quieres sorpresas.

Comandos útiles para ajustar y limpiar la situación de tu repo sin liarla demasiado: si quieres que el repositorio use el valor global, elimina la clave local; si prefieres forzar un valor en ese repo, configúralo sin –global. Para arreglar archivos ya mezclados, renormaliza y haz un commit agrupando los cambios de finales de línea.

git config --list --global
# Ver el valor global efectivo

git config --unset core.autocrlf
# Quitar el valor local y heredar el global

git config core.autocrlf true
# Fijar el valor solo en el repo actual (Windows)

git add --renormalize .
# Recorrerá el repo y homogeneizará line endings según la config

git commit -m 'Homogeneizados los cambios de línea'
# Sube un solo commit de normalización

Pero hay algo todavía mejor: un .gitattributes en la raíz que viaje con el código. Con la regla * text=auto le dices a Git que detecte los archivos de texto y gestione los saltos de línea como toca (LF en el repo; CRLF en working copy de Windows si aplica). Y puedes afinar por extensión, p. ej., forzar que los .sln de Visual Studio se mantengan como CRLF siempre.

* text=auto
# Homogeneiza automáticamente (LF en el repo)

*.sln text eol=crlf
# Asegura CRLF en soluciones de Visual Studio

Cuando introduzcas .gitattributes en un repo ya vivo, no te olvides de git add –renormalize . y de agrupar el commit. Así evitas que cada colaborador genere su “mega-commit de limpieza”. Es una de esas tareas que haces una vez y te quita problemas durante años.

Configurar el editor: VS Code, EditorConfig y Visual Studio

Tu editor también pinta mucho. En VS Code puedes fijar el salto de línea desde la barra de estado o con la opción files.eol. Si el proyecto usa LF, márcalo y listo; el editor guardará así sin que tengas que ir archivo por archivo. Es rápido y te evita diffs ruidosos.

Si en el equipo cada uno usa un editor distinto, incorporar EditorConfig (.editorconfig) en la raíz es mano de santo: define reglas como final de línea, codificación y espacio/tabulador de forma consistente. La mayoría de editores modernos lo respetan, y se integra fenomenal con Git y CI.

  Cómo gestionar grupos de usuarios en Windows 11 de forma sencilla y avanzada

Para quien utilice Visual Studio, hay un panel específico para guardar con una codificación y salto de línea concretos (Opciones de guardado avanzadas). Puedes acceder al flujo Archivo > Guardar Como > desplegable Guardar > Guardar con codificación, y también colocar Opciones de guardado avanzadas directamente en el menú Archivo para acceso rápido.

  1. Abre Tools > Personalizar.
  2. En la pestaña Comandos, elige Barra de menús y selecciona Archivo.
  3. Pulsa Añadir comando, categoría Archivo, y añade Opciones de guardado avanzadas.
  4. Recoloca con Subir/Bajar y cierra. Ya lo tienes a mano.

Con Visual Studio también puedes topar con archivos que traen otros separadores (NEL, LS, PS). El IDE intenta normalizarlos cuando detecta inconsistencias y te pedirá instrucción. Mantener .gitattributes y las opciones de guardar bien puestas evita que el proyecto se te llene de “casos exóticos”.

Más allá de CRLF y LF: NEL, LS, PS y compañía

Unicode considera como finales de línea ciertos puntos de código adicionales: NEL (U+0085), LS (U+2028) y PS (U+2029), además de VT (U+000B) y FF (U+000C). No son habituales en proyectos de app/web, pero aparecen en mainframes IBM (EBCDIC) y en algunos documentos procesados con herramientas antiguas o de nicho.

Por compatibilidad, Unicode replica los controles ASCII de siempre con el mismo valor numérico (CR y LF), y añade los nuevos para conversiones sin pérdida entre codificaciones (ej., mapear EBCDIC NL a Unicode NEL). Si te llega un archivo “raro”, un editor moderno suele mostrar o pedir normalizar.

Carácter Descripción Unicode
CR LF Retorno + avance U+000D + U+000A
LF Avance de línea U+000A
NEL Línea siguiente U+0085
LS Separador de línea U+2028
PS Separador de párrafo U+2029

En versiones antiguas del Bloc de notas de Windows ni siquiera LF se mostraba bien; hoy el soporte es mucho mejor, pero NEL sigue siendo problemático en algunos entornos. Por eso, de cara a repos y CI, mantener todo en LF en el repo y dejar a Git/editores el CRLF de la working copy en Windows es la jugada ganadora.

Lenguajes de programación y saltos de línea (\r, \n, y trampas)

En cadenas de texto, muchos lenguajes permiten secuencias de escape: \n = LF, \r = CR. Con eso compones CRLF como \r\n cuando hace falta, o insertas un LF “limpio” con \n. Pero ojo, porque no todos los runtimes se portan igual.

Casos a tener en mente: en Java, además de \r y \n, tienes %n (formateadores) y System.lineSeparator() para obtener el salto de línea del sistema de forma portable; en C#, Environment.NewLine hace lo propio; en PHP existe PHP_EOL; en Python, os.linesep. Si quieres imprimir según la plataforma, usa esas constantes en lugar de casarte con CRLF.

Cuidado especial con C y C++: en modo texto, la secuencia \n puede mapearse al salto de línea del sistema (en Windows, CRLF), y si tú imprimes \r\n puedes acabar generando CRCRLF. En modo binario, la cosa es literal. Esta sutilidad pilla desprevenido a más de uno cuando compila en Windows y testea en Linux.

En JavaScript/TypeScript, \n suele bastar para la mayoría de usos, pero si procesas entrada de usuarios de Windows verás \r\n y tendrás que normalizar al dividir líneas. Además, cuando generas HTML la maquetación final la controlan las etiquetas (p., br, p, h2…), no los caracteres \r o \n.

// C#
var s1 = "Primera\nSegunda";            // LF explícito
var s2 = "Primera" + Environment.NewLine + "Segunda"; // Salto del sistema

// Java
String a = "Uno\r\nDos";                 // CRLF explícito
String b = "Uno" + System.lineSeparator() + "Dos";    // Portátil

// Python
s = 'Linea1' + os.linesep + 'Linea2'

// JavaScript
const t = 'L1\nL2'; // Normaliza entrada si viene con \r\n

Si generas tráfico de red, recuerda que protocolos como HTTP, SMTP, FTP o IRC son taxativos: los encabezados y muchas líneas de control van con CRLF sí o sí. No “inventions”: ajusta la salida a la RFC o te encontrarás con servidores que rechazan las peticiones.

  Guía Completa para Usar el Modo Niños de Microsoft Edge: Seguridad y Diversión para los Peques

Cómo detectar y convertir finales de línea de forma fiable

No existe una “BOM” que te diga el tipo de salto de línea de un archivo: hay que mirar los bytes. En la práctica, las herramientas cuentan CR (0x0D) y LF (0x0A) y ven sus patrones: si aparecen emparejados, suele ser CRLF; si solo aparece 0x0A, es LF; si hay mezcla no consistente, tienes un batiburrillo que conviene arreglar.

Algunos editores detectan y avisan; VS Code lo muestra en la barra de estado; Visual Studio puede ofrecer normalizar. En Git, el paso seguro es definir .gitattributes y, si procede, renormalizar para alinear todo el árbol con la política. Tu repositorio (y tus revisiones) te lo agradecerán.

¿Y si trabajas con “formatos exóticos”? Editores como Notepad++ y VS Code manejan bien CRLF y LF, y suelen identificar LS/PS. Para NEL y casos de EBCDIC, a veces tocará pasar por una conversión previa de codificación además del salto de línea.

La estrategia ganadora en la mayoría de proyectos es simple: guarda en el repo con LF, habilita conversión automática en Windows, y bloquea excepciones puntuales con eol=crlf para archivos que lo necesiten (por ejemplo, .sln). Lo demás son sustos evitables.

Repos con saltos de línea mixtos: cómo arreglar el desaguisado

Es muy típico: partes del código vienen de Linux (LF) y otras se han tocado en Windows (CRLF). El resultado es un árbol con líneas mezcladas, diffs imposibles de leer y gente preguntándose por qué su script hoy no arranca. Toca poner orden.

Plan rápido y seguro:

  1. Añade .gitattributes con * text=auto y reglas específicas si hace falta (p. ej., *.sln text eol=crlf).
  2. Ejecuta git add –renormalize . para que Git recorra el repo y ajuste los saltos de línea según las reglas.
  3. Haz un commit único con un mensaje claro (ej., “Homogeneizados los cambios de línea”).
  4. Comunícalo al equipo y pide pull antes de seguir para minimizar conflictos.

Si tienes scripts sensibles (sh, py, etc.) asegúrate de que se guardan con LF y que no se deforma el shebang. Puedes forzarlo con patrones en .gitattributes o revisarlo en tu editor antes de confirmar.

Para Visual Studio, si detecta saltos inconsistentes, te propondrá normalizar. Acepta, revisa el diff, y acompáñalo del commit de renormalización anterior para que todo quede redondo.

Desde ese momento, con .gitattributes y core.autocrlf bien puestos, se acabaron los parches de “esta vez pasó por CRLF”. Y si alguien abre el proyecto en Linux o macOS, todo seguirá igual porque en el repo los archivos quedan guardados con LF.

formatos soportados por Microsoft Office y cuándo es mejor usar cada uno
Artículo relacionado:
Formatos de Microsoft Office: qué son y cuándo usar cada uno

Deja un comentario