- No Git,
help.autocorrect=1 corrige um comando digitado errado e o executa após esperar apenas 0,1 segundo, o que na prática fica muito próximo de uma execução imediata para o usuário confirmar ou cancelar
- Esse comportamento não é o padrão do Git; na configuração padrão, ele não executa um comando desconhecido e apenas mostra comandos semelhantes antes de encerrar
- Em uma discussão de 2008,
help.autocorrect deixou de ser booleano e passou a representar um tempo de espera em decissegundos, fazendo com que 1 seja interpretado não como true, mas como uma espera de 0,1 segundo
- Atualmente,
help.autocorrect aceita 0, valores positivos, immediate, prompt e never, e prompt é a opção mais segura para quem quer executar após confirmação
- A estimativa de comandos do Git é baseada em uma distância de Levenshtein modificada, e Scott Chacon propôs um patch para tratar
1 e strings booleanas de forma mais natural
Como git pushy acaba virando git push
- Quando
@dhh digitou git pushy, o Git inferiu que se tratava de git push e esperou apenas 0,1 segundo antes de executar
- 0,1 segundo é pouco demais para o usuário ler o comando, decidir se está correto e cancelá-lo
- Esse comportamento não é o padrão do Git; ele aparece quando a configuração
help.autocorrect está ativada
O comportamento padrão e o surgimento de help.autocorrect
- A reação padrão do Git é não executar um comando desconhecido e, em vez disso, mostrar possíveis comandos com base na similaridade entre strings antes de encerrar
- Exemplo:
git pushy pode indicar que push é o comando mais parecido
- Originalmente, o Git apenas respondia que aquilo “não é um comando Git” para comandos desconhecidos
- Em 2008, Johannes Schindelin propôs um pequeno patch para percorrer os comandos conhecidos, encontrar o mais parecido e executá-lo se houvesse apenas um candidato suficientemente próximo
- Alex Riesen enviou um patch para controlar isso pela configuração
help.autocorrect, que no início era booleana
- Em configurações do Git, valores booleanos podem interpretar
1 como true
- Por isso, no contexto original,
help.autocorrect=1 podia parecer um valor para ativar a autocorreção
Por que 1 virou 0,1 segundo
- Junio Hamano sugeriu que
help.autocorrect não fosse apenas um booleano, mas o número de decissegundos a esperar antes da execução
- Decissegundo é uma unidade de 0,1 segundo
- A intenção era dar ao usuário uma chance de apertar
^C
- No patch que acabou sendo aceito, o valor da configuração passou a representar o tempo de espera
- Como resultado,
help.autocorrect=1 deixou de significar “ativar o recurso” e passou a significar “esperar 1 decissegundo, isto é, 0,1 segundo, e então executar”
- O motivo de o decissegundo ter sido escolhido como unidade de tempo adequada não ficou registrado na discussão
Valores de configuração disponíveis hoje
- Segundo a documentação do Git,
help.autocorrect aceita os seguintes valores
0: valor padrão; apenas mostra comandos sugeridos
- valores positivos: executa o comando sugerido após o número especificado de decissegundos
immediate: executa o comando sugerido imediatamente
prompt: mostra a sugestão e pergunta se deve executar
never: não executa nem mostra o comando sugerido
- Se você quer confirmar antes de executar,
prompt é a opção mais sensata para a maioria dos usuários
- Um exemplo de configuração é o seguinte
git config --global help.autocorrect prompt
- Depois disso, ao digitar algo como
git pushy, ele perguntará em [y/N] se deve executar push
Como o Git escolhe comandos parecidos
- O Git não tenta adivinhar comandos de forma irrestrita; a partir de certo ponto, ele considera que a distância é grande demais e deixa de sugerir candidatos
- O comportamento nos exemplos é o seguinte
git bass é considerado próximo o bastante de rebase para pedir confirmação antes de executar
git bassa já é considerado distante demais para ser tratado como rebase, então o candidato não é executado
git dm mostra tanto am quanto rm como comandos parecidos
git dma passa a corresponder apenas a am
- Essa lógica é baseada em um algoritmo de distância de Levenshtein modificado
- Ele calcula o custo de edição de caracteres necessário para transformar uma string em outra
- Algumas operações são tratadas como mais caras do que outras
- O Git tem um cutoff fixo em código; se o custo em relação a um comando conhecido for alto demais, ele entende que o usuário digitou algo muito diferente e não faz inferência
O patch que tenta mudar a interpretação de 1
- Como
help.autocorrect=1 é, do ponto de vista humano, praticamente igual a immediate, Scott Chacon escreveu um pequeno patch para interpretar 1 não como espera de 0,1 segundo, mas como execução imediata
- Junio Hamano pediu que não fosse feito tratamento especial apenas para
"1", mas que também fossem interpretadas corretamente strings booleanas como yes, no, true e off
- A segunda versão do patch está avançando de forma a incluir também esse tratamento de strings booleanas
- Se o patch for incorporado, versões futuras do Git poderão reduzir a confusão em torno de
help.autocorrect
1 comentários
Comentários no Hacker News
Nos anos 70, Hal Finney estava fazendo um interpretador BASIC para o Mattel Intellivision caber em uma ROM de 2 KB, e cada byte era precioso.
Para indicar erro de sintaxe, ele reduziu todas as mensagens de erro para
EH?, e ainda acho engraçado que ele tinha bastante orgulho disso.EH?também pareceria uma boa resposta de parser de texto em jogos antigos de ficção interativa.Meio relacionado: em algumas variantes antigas de BASIC, dava para escrever a instrução
PRINTcomo?, mas acho que isso tinha mais a ver com reduzir o tempo de digitação no REPL do que com economizar memória.edusa só um?para todos os erros, então há uma economia 3 vezes maior.Eh?foi no JOSS, da 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
A memória era de cerca de 5 KB, mas, comparada ao Intellivision, a máquina pesava cerca de 5.000 libras.
Então você pode chutar uma palavra, ficar com as 5 letras todas verdes, e ainda assim ela não ser nenhuma das duas respostas. Nesses casos, fiz aparecer apenas
Huh?à direita, e as pessoas gostam dessa parte.A causa raiz é que o nome da configuração foi mal escolhido.
Se a configuração original tivesse sido nomeada de forma booleana, como
help.autocorrect_enabled, a solicitação de aceitar um valor inteiro e interpretá-lo em unidades de 0,1 segundo não teria feito sentido. Em vez disso, teria sido necessária outra configuração, comohelp.autocorrect_accept_after_dsec, edsecé tão incomum que quem fosse usar teria que pesquisar.Em revisão de código, sempre exijo isso: se puder haver ambiguidade, o nome da variável precisa incluir a unidade. Por exemplo,
int timeoutdeve virarint timeout_msec.Em nomes de configuração, isso é 100 vezes mais importante, porque configurações são parte da interface pública e não dá para mudá-las depois.
No contexto de C++, minha regra geral é que
void FooBar(std::chrono::milliseconds timeout);está ok. Como é uma assinatura de função, você vê o tipo junto.Mas, em uma variável,
timeoutnão está ok. Em 99% dos casos, o uso real aparece comoauto timeout = gl_timeout;ouFooBar(timeout);.Como
autoé muito usado em C++, fica bem trabalhoso rastrear o tipo exato quando isso importa.Quando trabalho com C++, uso uma IDE ou um editor com servidor de linguagem, mas não tenho tempo de passar o mouse a cada 5 segundos para conferir o tipo.
Se a mensagem dissesse “executando em 1 ms”, eu teria verificado a configuração na hora.
TimoutSec=60quantoTimeoutSec=1min.Acho que teria sido melhor não colocar a unidade no nome. Mas, tirando esse caso peculiar, concordo totalmente.
A melhor alternativa que encontrei até agora é fazer o valor receber a unidade. Por exemplo, aceitar
5 secondsou5s, e tratar simplesmente1como um valor inválido.intem si e recomendaria, em vez disso, uma classe de valor que carregue a unidade corretamente.Por exemplo, algo como
Second(2)ouMillisecond(2000).Claro que isso depende dos recursos e das convenções da linguagem.
O xmobar também usa décimos de segundo, mas em um lugar ainda mais problemático: a configuração que declara com que frequência cada seção deve ser atualizada.
Os números da configuração de exemplo são pequenos demais para parecerem milissegundos, então levam a supor, razoavelmente, que sejam segundos; com isso, o comando acaba sendo executado 10 vezes mais frequentemente do que o pretendido.
Já vi várias explosões acidentais de carga decorrentes desse problema.
Parece um design bem ruim.
Mas o item 1 foi resultado de uma leitura equivocada do texto; o “valor anterior” nunca existiu no git.
1=truepor1=atraso de confirmação de 0,100 ms, quase sempre deve ser evitada. Se houvesse um valor existente, eu até entenderia querer removê-lo, mas o certo seria também mudar o nome da configuração.help.autocorrectser um tempo, medido em uma unidade que não é padrão para a maioria dos usuários, é simplesmente ruim. A ativação deveria ser booleana, e o tempo de confirmação deveria poder ser ajustado com um valor decimal.Essa mudança aconteceu em 2008, durante a revisão de código do patch inicial que adicionaria a opção como booleana, antes de ser commitada na árvore principal do git.
Isto está mais para um ramo lateral que cresceu organicamente do que para design.
Vejo isso como um bom exemplo de excesso incremental de recursos (creeping featurism).
Na melhor das hipóteses, introduz complexidade desnecessária; na pior, faz as pessoas que dependem disso prestarem menos atenção ao que estão fazendo.
É tão difícil assim apertar a seta para cima e corrigir o erro? Executar automaticamente algo “mais ou menos certo” é uma receita para fazer coisas não intencionais.
O erro foi aqui. Em vez de reaproveitar a configuração existente com outro significado, deveriam ter adicionado uma nova configuração
help.autocorrectdeveria ter ficado para ligar/desligar, ehelp.autocorrect.millisecondspara definir quanto tempo esperarHá erros parecidos em outros sistemas. Por exemplo, no MySQL,
innodb_flush_log_at_trx_commité desativado quando vale 0, ativado quando vale 1, e o 2 foi adicionado depois com um significado especial1significaAgora
1continua sendo booleano verdadeiro, enquanto outros inteiros viram unidades de 0,1 segundo, afundando ainda mais no problemaÉ uma lógica suspeita, como o famoso
no == falsedo YAMLO tempo de reação aleatória mais rápido registrado é de cerca de 1,5 ds e, por coincidência, o tempo médio de reação de gamers também fica por aí, mas reações não aleatórias podem ser muito mais rápidas. Por exemplo, ao reagir no ritmo de uma batida
Se quiser ir tão rápido assim, é possível, e a velocidade de invocação também deve ser relativamente estável. Deve ficar na ordem de alguns milissegundos
Há um ano ativei a correção automática e configurei para 3 segundos, e percebi duas coisas
Depois de ler este texto, tive finalmente o impulso para desativá-la após um ano
Claro, isso também “polui” o histórico do shell
Dá no mesmo se você voltar no histórico e reutilizar o último comando errado só porque ele funciona de qualquer jeito
Unidades de 0,1 segundo são uma escolha realmente peculiar
Seria melhor especificar atrasos em milissegundos ou segundos, e ambos são muito mais comuns em computação
decisecondsfosse uma unidade específica do git, significando algo como decision-seconds, “segundos necessários para tomar uma decisão” xDPara constar, inglês não é minha língua nativa, mas venho de uma região civilizada que usa o sistema métrico
A diferença entre 0 segundo e 1 segundo é perceptivelmente longa quando se está esperando algo, mas a diferença entre n milissegundos e n+1 milissegundos é pequena demais para ser útil
O tempo de reação varia conforme o tipo de estímulo; o auditivo é um pouco mais rápido que o visual, e o tátil é um pouco mais rápido ainda, ficando em torno de 90–180 ms
Então, se o git desse um tapa em vez de mostrar uma mensagem de erro, talvez houvesse tempo de reagir por pouco
10 ms seriam suficientes para isso?
Ao ler este texto, lembrei de arqueologia de software e do termo “programador arqueólogo”
Pelo segundo conceito, devemos agradecer a Vernor Vinge
Mas o conceito só é insinuado rapidamente no prólogo e depois não aparece mais. Os efeitos da arqueologia são relevantes para a trama, mas o “arqueólogo de software” não era um personagem significativo na narrativa
Fiquei com a sensação de ter sido enganado