FuncionesPreciosDocumentaciónBlog
Obtener mote
← Blog
Ingeniería·7 de septiembre de 2026·4 min de lectura

Para que el documento no quede vacío después de `git checkout`, observamos los bytes en vez del reloj

¿Alguna vez has cambiado de rama y un documento que tenías abierto se ha quedado en blanco? Mientras hacíamos una captura de pantalla para el blog, vimos esa escena en nuestra aplicación y, ya que íbamos a arreglarla, solucionamos también otro error más silencioso.

m
mote
El banner que aparece cuando un documento que se está editando cambia desde fuera. Permite elegir entre volver a cargarlo o seguir editándolo, y en la barra de estado todavía quedan 13 B sin guardar.
El banner que aparece cuando un documento que se está editando cambia desde fuera. Permite elegir entre volver a cargarlo o seguir editándolo, y en la barra de estado todavía quedan 13 B sin guardar.

mote confía en los archivos tal como son. El contenido de la pantalla coincide con los bytes del disco y, al guardar, también escribe esos mismos bytes sin modificarlos.

Pero ¿qué ocurre si un archivo cambia fuera de la aplicación? Si mote no se da cuenta, la próxima vez que se guarde podría sobrescribir el contenido escrito por otra persona.

Descubrimos este problema mientras hacíamos capturas de pantalla. Estábamos preparando la pantalla de «bytes que cambian» alternando entre ramas, y a veces el documento se quedaba bloqueado en blanco.

Dos problemas ocultos tras la pantalla en blanco

git checkout no cambia un archivo de una sola vez. Borra el archivo existente, crea uno nuevo y después escribe su contenido.

El monitor de archivos informa de este proceso mediante varios eventos. Sin embargo, mote leía el archivo en cuanto llegaba el primer evento. Como todavía no se había escrito el contenido, a veces terminaba leyendo un archivo vacío.

Al volver a leer el archivo, también creaba de nuevo el monitor. Mientras tanto, los eventos que aún quedaban en el monitor anterior desaparecían y la pantalla se quedaba bloqueada en blanco.

También había un problema más peligroso.

Después de guardar, mote consideraba que todos los eventos recibidos durante 1,5 segundos eran «cambios realizados por mí» y los ignoraba. Pero, dentro de ese intervalo, un formateador o un hook de guardado también podía volver a modificar el archivo.

De hecho, si el archivo se modificaba 0,3 segundos después de guardarlo, mote no mostraba ningún cambio. Si el usuario volvía a guardar, el contenido modificado desde fuera desaparecía silenciosamente.

Uno era visible y el otro no. La causa era la misma.

Estábamos juzgando los cambios del archivo por el tiempo, no por su contenido.

Comparamos el contenido en lugar del tiempo

Ahora, cuando llega un evento del archivo, no lo leemos de inmediato. Esperamos 200 ms y reiniciamos la espera cada vez que llega un evento nuevo.

Una vez terminado el proceso de borrar, crear y escribir el archivo, leemos solamente una vez su estado final. Los temporizadores antiguos se invalidan mediante un número de generación. Tampoco creamos temporizadores que sigan ejecutándose cuando no ocurre nada.

El contenido leído se compara con los últimos bytes del disco que vio el búfer.

Si son iguales, significa que la aplicación los guardó o que se volvió a escribir el mismo contenido. Si son distintos, se trata de un verdadero cambio externo. No importa si han pasado 0,1 segundos o 1 segundo desde que se guardó.

Cuando volvemos a leer el mismo archivo, también mantenemos el monitor. Así evitamos que desaparezcan eventos mientras se sustituye el monitor.

Solo preguntamos cuando se está editando

Después de detectar un cambio externo, comprobamos el estado del usuario.

Si hay cambios sin guardar, mostramos un banner. El usuario puede elegir entre volver a cargar el archivo modificado o seguir editando el contenido actual. Cualquiera de las dos opciones puede provocar la pérdida de contenido, así que la aplicación no toma la decisión por el usuario.

Si no se está editando, cargamos de inmediato el contenido nuevo. No mostramos el banner y conservamos la posición del cursor y del desplazamiento. Al leer un documento mientras se alterna entre ramas, resulta más natural mantener el lugar por donde se estaba leyendo que mostrar una notificación.

Archivo modificado desde fuera cuando no se está editando. El contenido se actualizó sin mostrar un banner, y desaparecieron el indicador de edición del título y los bytes pendientes de la barra de estado.
Archivo modificado desde fuera cuando no se está editando. El contenido se actualizó sin mostrar un banner, y desaparecieron el indicador de edición del título y los bytes pendientes de la barra de estado.

Tampoco tomamos una decisión inmediata cuando desaparece un archivo. Como otro editor podría estar cambiando el nombre del archivo, volvemos a comprobarlo 300 ms después.

Si el archivo sigue sin existir en ese momento, se lo comunicamos al usuario. El contenido en el que estaba trabajando permanece en el búfer y, al volver a guardarlo, se crea el archivo.

Comprobamos seis situaciones en un entorno real

Es difícil comprobar este problema únicamente mediante pruebas unitarias. Esto se debe a que ocurre cuando el monitor de archivos, el disco real y el gestor de ventanas funcionan conjuntamente.

Por eso creamos comprobaciones que se ejecutan en un entorno real.

Comprobamos si el búfer sigue al archivo aunque se cambie de rama diez veces y si los cambios se reflejan aunque el archivo se modifique 300 ms después de guardarlo. También comprobamos que no aparezca ninguna notificación cuando la propia aplicación guarda el archivo y que, si se produce un cambio externo durante la edición, muestre el banner sin perder el contenido escrito.

En total son seis comprobaciones. Las ejecutamos en cada lanzamiento.

Salida de la ejecución de tools/e2e/external.sh en una pantalla real. Las seis líneas muestran ok y la última línea dice PASS=6 FAIL=0.
Salida de la ejecución de tools/e2e/external.sh en una pantalla real. Las seis líneas muestran ok y la última línea dice PASS=6 FAIL=0.

Tratar el archivo como la verdad no termina al escribir exactamente el contenido guardado.

Cuando el archivo cambia sin que lo sepamos, tampoco debemos pasar por alto ese cambio.

← AnterioresCómo evitamos que los archivos se corrompan aunque la aplicación se cierre durante el guardado
Siga las novedades por RSS.
Que solo quede la escritura.
Español
© 2026 mote