- En Git,
help.autocorrect=1 corrige un comando mal escrito y luego lo ejecuta tras esperar solo 0.1 segundos, así que en la práctica se acerca a una ejecución inmediata y no da tiempo real para confirmar o cancelar
- Este comportamiento no es el predeterminado de Git; con la configuración por defecto, no ejecuta un comando desconocido y solo muestra comandos similares antes de salir
- En una discusión de 2008,
help.autocorrect dejó de ser booleano y pasó a representar un tiempo de espera en decisegundos, por lo que 1 se interpreta no como true, sino como una espera de 0.1 segundos
- Actualmente,
help.autocorrect admite 0, valores positivos, immediate, prompt y never; si quieres ejecutar tras confirmar, prompt es una opción más segura
- La deducción de comandos en Git se basa en una distancia de Levenshtein modificada, y Scott Chacon propuso un parche para manejar de forma más natural
1 y las cadenas booleanas
Cómo git pushy termina ejecutándose como git push
- Cuando
@dhh escribió git pushy, Git dedujo que quería decir git push y esperó solo 0.1 segundos antes de ejecutarlo
- 0.1 segundos es demasiado poco para que una persona lea el comando, decida si es correcto y lo cancele
- Este comportamiento no es el predeterminado de Git, sino que aparece cuando la opción
help.autocorrect está activada
El comportamiento predeterminado y el nacimiento de help.autocorrect
- La respuesta predeterminada de Git es no ejecutar un comando desconocido, sino mostrar posibles comandos según la similitud de cadenas y luego salir
- Ejemplo:
git pushy puede mostrar que push es el comando más parecido
- Originalmente, Git solo respondía a un comando desconocido con algo como “no es un comando de Git”
- En 2008, Johannes Schindelin propuso un pequeño parche para recorrer los comandos conocidos, encontrar el más parecido y, si había un solo candidato suficientemente cercano, ejecutarlo
- Alex Riesen envió un parche para controlar esto con la opción
help.autocorrect, que al inicio era booleana
- En la configuración de Git, un valor booleano puede interpretar
1 como true
- Por eso, en su contexto original,
help.autocorrect=1 podía parecer una forma de activar la autocorrección
Por qué 1 terminó significando 0.1 segundos
- Junio Hamano propuso que
help.autocorrect no fuera un simple booleano, sino la cantidad de decisegundos a esperar antes de ejecutar
- Un decisegundo equivale a 0.1 segundos
- La intención era darle al usuario la oportunidad de presionar
^C
- En el parche que finalmente se aceptó, el valor de la opción pasó a representar un tiempo de espera
- Como resultado,
help.autocorrect=1 ya no significa “activar la función”, sino “esperar 1 decisegundo, es decir, 0.1 segundos, y luego ejecutar”
- No quedó registrado en la discusión por qué se eligió el decisegundo como unidad de tiempo adecuada
Qué valores de configuración se pueden elegir hoy
- Según la documentación de Git,
help.autocorrect admite los siguientes valores
0: valor predeterminado; solo muestra el comando sugerido
- valores positivos: ejecuta el comando sugerido tras el número indicado de decisegundos
immediate: ejecuta el comando sugerido de inmediato
prompt: muestra la sugerencia y pregunta si debe ejecutarla
never: ni ejecuta ni muestra el comando sugerido
- Si quieres ejecutar solo después de confirmar,
prompt suele ser una opción más razonable para la mayoría de usuarios
- Un ejemplo de configuración sería el siguiente
git config --global help.autocorrect prompt
- Después, si escribes algo como
git pushy, te preguntará con [y/N] si quieres ejecutar push
Cómo elige Git los comandos parecidos
- Git no intenta adivinar comandos sin límite; llega un punto en que considera que la distancia es demasiado grande y ya no propone candidatos
- Algunos ejemplos de comportamiento
git bass está lo bastante cerca de rebase como para mostrar la confirmación de ejecución
git bassa ya se considera demasiado lejos como para tratarlo como rebase
git dm muestra tanto am como rm como comandos similares
git dma se empareja solo con am
- Esta lógica se basa en un algoritmo de distancia de Levenshtein modificado
- Calcula el costo de edición de caracteres necesario para convertir una cadena en otra
- Algunas operaciones se consideran más costosas que otras
- Git tiene un cutoff codificado de forma fija; si el costo respecto a un comando conocido es demasiado alto, asume que el usuario escribió algo muy distinto y no hace una deducción
El parche para cambiar cómo se interpreta 1
- Como
help.autocorrect=1 en términos humanos es prácticamente lo mismo que immediate, Scott Chacon escribió un pequeño parche para interpretar 1 no como una espera de 0.1 segundos, sino como ejecución inmediata
- Junio Hamano pidió no tratar solo
"1" como caso especial, sino interpretar correctamente también cadenas booleanas como yes, no, true y off
- La segunda versión del parche avanza en esa dirección e incluye el manejo de estas cadenas booleanas
- Si el parche se integra, en futuras versiones de Git podría reducirse la confusión en torno a
help.autocorrect
1 comentarios
Comentarios de Hacker News
En los años 70, Hal Finney estaba haciendo que un intérprete BASIC para Mattel Intellivision cupiera en una ROM de 2 KB, y cada byte era valioso.
Todavía me da risa que, para mostrar errores de sintaxis, redujo todos los mensajes de error a
EH?, y que él estaba bastante orgulloso de eso.EH?también quedaría muy bien como respuesta del parser de texto en un viejo juego de ficción interactiva.Algo relacionado: en algunas variantes antiguas de BASIC se podía escribir la sentencia
PRINTcomo?, aunque creo que eso tenía más que ver con ahorrar tiempo al teclear en el REPL que con ahorrar memoria.edusa solo un?para todos los errores, así que ahorra 3 veces más.Eh?como respuesta de un intérprete fue en JOSS de RAND.[https://en.wikipedia.org/wiki/JOSS#/media/File:JOSS_Session....](https://en.wikipedia.org/wiki/JOSS#/media/File:JOSS_Session.jpg)
https://en.wikipedia.org/wiki/JOSS
Tenía unos 5 KB de memoria, pero, comparado con la Intellivision, la máquina pesaba unas 5,000 libras.
Así que puedes adivinar una palabra y que las 5 letras queden todas en verde, pero aun así no sea ninguna de las dos respuestas. Cuando pasa eso, a la derecha simplemente hice que aparezca
Huh?, y a la gente le gusta esa parte.La causa de fondo es que el nombre de la configuración está mal elegido.
Si la configuración original se hubiera llamado algo con pinta de booleano, como
help.autocorrect_enabled, habría sido absurdo pedir que aceptara un valor entero e interpretarlo en unidades de 0.1 segundos. En cambio, habría hecho falta otra configuración comohelp.autocorrect_accept_after_dsec, y comodseces tan poco común, cualquiera que la usara no tendría más remedio que buscar qué significa.En las revisiones de código siempre pido este tipo de cosas. Si puede ser ambiguo, el nombre de la variable debe incluir la unidad. Por ejemplo,
int timeoutdebería serint timeout_msec.En los nombres de configuración esto es 100 veces más importante. Las configuraciones son parte de la interfaz pública, así que no se pueden cambiar después.
En el contexto de C++, una regla aproximada sería que
void FooBar(std::chrono::milliseconds timeout);está bien, porque es una firma de función y al verla también se ve el tipo.Pero en una variable,
timeoutno está bien. En el 99% de los casos, el uso real se ve comoauto timeout = gl_timeout;oFooBar(timeout);.Como en C++ se usa mucho
auto, seguir el tipo exacto cuando importa se vuelve bastante molesto.Cuando trabajo en C++ uso un IDE o un editor con servidor de lenguaje, pero no tengo tiempo de pasar el mouse cada 5 segundos para comprobar el tipo.
Si hubiera visto un mensaje que dijera “se ejecutará después de 1 ms”, habría revisado la configuración de inmediato.
TimoutSec=60comoTimeoutSec=1min.Creo que habría sido mejor no poner la unidad en el nombre. Aunque, salvo por ese caso particular, estoy totalmente de acuerdo.
La mejor alternativa que encontré hasta ahora es hacer que el valor reciba una unidad. Por ejemplo, permitir
5 secondso5s, y tratar simplemente1como un valor inválido.inty recomendaría una clase de valor que lleve correctamente la unidad.Por ejemplo, algo como
Second(2)oMillisecond(2000).Claro que esto depende de las características y convenciones del lenguaje.
xmobar también usa unidades de 0.1 segundos en un lugar similar, pero más problemático. Es la configuración que declara con qué frecuencia se actualiza cada sección.
Los números de la configuración de ejemplo son demasiado pequeños como para que parezcan milisegundos, así que uno asume razonablemente que son segundos, y como resultado termina ejecutando comandos 10 veces más seguido de lo previsto.
He visto varias veces picos accidentales de carga originados por este problema.
Parece un diseño bastante malo.
Aunque el punto 1 fue resultado de leer mal el artículo, y el “valor anterior” nunca existió en git.
1=truea1=retraso de confirmación de 0.100 ms. Si hubiera existido un valor previo, quizá querrías eliminarlo, pero lo correcto sería cambiar también el nombre de la configuración.help.autocorrectsea tiempo y que esté medido en una unidad no estándar para la mayoría de los usuarios simplemente está mal. La activación debería recibirse como booleano, y el tiempo de confirmación debería poder ajustarse con un valor decimal.Ese cambio ocurrió en 2008, durante la revisión de código del parche inicial que intentaba agregar esa opción como booleano, antes de que se hiciera commit al árbol principal de git.
Esto se parece más a una rama lateral que creció orgánicamente que a un diseño.
Creo que este es un buen ejemplo de exceso progresivo de funcionalidades (creeping featurism).
En el mejor de los casos introduce complejidad innecesaria, y en el peor hace que la gente que depende de eso preste menos atención a lo que está haciendo.
¿Tan difícil es presionar la flecha hacia arriba y corregir el error? Ejecutar automáticamente algo “más o menos correcto” es la receta para hacer cosas no intencionales.
El error estaba aquí. En vez de reutilizar una configuración existente con otro significado, debieron agregar una configuración nueva
help.autocorrectdebió separarse en activar/desactivar, yhelp.autocorrect.millisecondsen cuánto esperarHay errores parecidos en otros sistemas. Por ejemplo, en MySQL,
innodb_flush_log_at_trx_commitestá desactivado si es 0, activado si es 1, y el 2 se agregó después con un significado especial1Ahora
1se mantiene como verdadero booleano, mientras otros enteros se vuelven unidades de 0.1 segundos, hundiéndose aún másEs una lógica dudosa, como el infame
no == falsede YAMLEl tiempo de reacción aleatorio más rápido registrado ronda los 1.5 ds, y casualmente el tiempo de reacción promedio de un gamer también está por ahí, pero las reacciones no aleatorias pueden ser mucho más rápidas. Por ejemplo, cuando se reacciona siguiendo un ritmo
Si quieres ir así de rápido, se puede, y la velocidad de invocación también debería ser relativamente estable. Probablemente del orden de unos pocos milisegundos
Hace un año activé la autocorrección y la configuré en 3 segundos, y noté dos cosas
Después de leer este artículo, tuve motivo suficiente para desactivarla tras un año
Aunque, claro, eso también “contamina” el historial de la shell
Es lo mismo si retrocedes en el historial y vuelves a usar tal cual el último comando mal escrito solo porque de todos modos funciona
Las unidades de 0.1 segundos son una elección realmente peculiar
Para los retardos conviene más especificar milisegundos o segundos, y ambos son mucho más comunes en computación
decisecondsera una unidad propia de git, algo como decision-seconds, es decir, “segundos necesarios para tomar una decisión” xDPara que conste, el inglés no es mi lengua materna, pero vengo de una región civilizada que usa el sistema métrico
La diferencia entre 0 y 1 segundo se nota mucho cuando esperas algo, pero la diferencia entre n milisegundos y n+1 milisegundos es demasiado pequeña para ser útil
El tiempo de reacción varía según el tipo de estímulo; el auditivo es un poco más rápido que el visual, y el táctil un poco más rápido todavía, de unos 90~180 ms
Así que si git te diera un golpe en vez de mostrar un mensaje de error, tal vez apenas tendrías tiempo de reaccionar
¿10 ms serían suficientes para eso?
Leer este artículo me recordó la arqueología de software y la idea del “programador arqueólogo”
Por lo segundo hay que darle las gracias a Vernor Vinge
Pero el concepto apenas se insinúa en el prólogo y luego no aparece en absoluto. Los efectos de la arqueología sí tienen relación con la trama, pero el “arqueólogo de software” no era un personaje significativo en la narración
Sentí que me habían engañado