Introdução
A Little Pine Goods prepara orçamentos de pequenos presentes para retirada. Um cliente informa que a oferta FRIEND10 deixou de conceder o desconto prometido. O histórico recente também contém atualizações úteis de produtos, textos e retirada, portanto voltar a loja inteira a uma versão antiga perderia trabalho válido.
Execute um pedido normal e o pedido de presente com problema; depois, use um teste de negócio determinístico preparado para classificar versões antigas. Pratique um pouco a busca binária manual do Git antes de deixar o mesmo teste automatizar a busca. Compare o primeiro snapshot incorreto com seu pai direto, saia da busca e corrija a loja atual, mantendo as atualizações posteriores. Entregue um arquivo completo de orçamento para o cliente, além do commit de correção.
Os pré-requisitos são navegação básica no terminal, commits, branches e leitura simples de log/diff. Git bisect, cópias temporárias com HEAD destacado, status de saída dos testes e a pequena edição do arquivo de ofertas são explicados aqui. O Python e o programa de orçamentos estão preparados; você os executará sem escrever Python. Trata-se de um histórico Git local real e uma ferramenta de orçamentos baseada em arquivos em uma única máquina de treinamento, com pedidos fictícios e preços em EUR. Não é necessário site, conta hospedada nem implantação em rede. Use o Terminal padrão. A duração de 50 minutos é uma estimativa do autor.
Encontre o Primeiro Orçamento Incorreto
Nesta etapa, estabeleça o resultado de negócio correto, teste snapshots históricos reais e identifique o limite em que o desconto passou a estar errado.
Comece em Terminal e entre no repositório da loja:
cd /home/labex/project/quote-desk/shop
cd altera o diretório deste terminal. Se digitar um caminho incorretamente, use pwd para exibir sua localização e ls para listar esse diretório; depois, repita o cd completo acima. Erros comuns de navegação não exigem restaurar a VM ao estado inicial.
Leia a solicitação do cliente. cat exibe um arquivo de texto; .. significa o diretório pai:
cat ../request.txt
FRIEND10 promete 10% de desconto sobre o subtotal dos itens. Não há frete nem imposto. O pedido de presente é de três canecas de acampamento a EUR 16.00 cada: subtotal EUR 48.00, desconto EUR 4.80, total EUR 43.20. O catálogo, o pedido e a política existentes são os fatos de negócio; não os altere para se ajustarem a um resultado incorreto.
Execute primeiro um pedido normal. python3 executa o programa fornecido quote.py; seu argumento seguinte é o arquivo de pedido preparado. Você não precisa editar nem compreender o código-fonte Python:
python3 quote.py ../orders/plain.order
O pedido de uma caneca usa o cupom NONE. Espere subtotal e total EUR 16.00, desconto EUR 0.00, a mensagem de boas-vindas atual e retirada no sábado até 16:00. Isso estabelece um orçamento normal útil.
Execute o pedido relatado:
python3 quote.py ../orders/gift.order
Para ler o status de saída nativo do último comando, use o valor do shell $?. echo exibe esse valor. Execute-o imediatamente após o comando de orçamento:
echo $?
Espere 0: o programa foi executado com sucesso, embora o resultado monetário esteja errado.
O programa funciona, mas o orçamento está errado: desconto EUR 0.48 e total EUR 47.52. Uma saída bem-sucedida do programa é diferente de uma resposta de negócio correta.
O teste preparado fica fora do repositório para que colocar versões antigas na cópia de trabalho não possa substituí-lo. Ele executa o programa real de orçamentos para várias quantidades e um controle sem cupom, comparando os resultados completos com a política de ofertas inalterada. Execute-o:
python3 /opt/labex/quote-desk/check.py
Leia imediatamente o status deste teste, usando o mesmo valor do shell:
echo $?
Espere 1: este teste detecta a divergência de negócio.
Espere linhas FAIL para FRIEND10 e um status de saída nativo de 1. Os controles NONE passam. O teste retorna 0 para orçamentos corretos, 1 para esta falha de negócio e 128 se não conseguir testar uma versão; a impossibilidade de testar deve interromper a busca, não ser presumida como uma regressão de desconto. Este histórico preparado não tem falhas de compilação nem versões ignoradas.
Inspecione a branch atual e o estado limpo. branch --show-current exibe a branch; --short produz uma lista compacta de arquivos:
git branch --show-current
git status --short
Espere main e nenhuma saída de arquivos alterados. Mantenha a loja limpa durante a busca. Leia seu histórico: --no-pager exibe a saída diretamente em vez de entrar em um visualizador com rolagem, --oneline resume as entradas e --decorate identifica branches e tags:
git --no-pager log --oneline --decorate
A tag fixa incident-tip marca a ponta atual recebida, e known-good marca a versão anterior que funcionava. Os assuntos dos commits descrevem o trabalho, mas sua redação não comprova quando o orçamento falhou. Preserve as duas tags e todos os commits recebidos.
A opção --revision do teste executa o snapshot selecionado de um commit em um diretório temporário isolado, sem alterar sua cópia de trabalho nem corrigi-la. Estabeleça as duas extremidades com comportamento real:
python3 /opt/labex/quote-desk/check.py --revision known-good
python3 /opt/labex/quote-desk/check.py --revision incident-tip
O primeiro comando deve passar com status 0. O segundo deve falhar com status 1. Uma versão correta e uma versão posterior incorreta delimitam a busca. Este exercício tem uma única introdução da falha e nenhuma correção posterior nesse intervalo.
Classifique Duas Versões Manualmente
O bisect do Git reduz esse intervalo testando versões entre os limites. Comece com a revisão sabidamente incorreta primeiro e a sabidamente correta em segundo:
git bisect start incident-tip known-good
O Git coloca um snapshot intermediário na cópia de trabalho e exibe o intervalo restante. Durante a busca, HEAD destacado significa que você está vendo um commit diretamente, em vez de mover a main. Não edite nem crie commits nessas versões temporárias.
Execute o mesmo teste no snapshot que está na cópia de trabalho:
python3 /opt/labex/quote-desk/check.py
Esta primeira seleção preparada falha com status 1. Classifique essa versão observada como incorreta; bad descreve o resultado do teste de negócio, não a mensagem do commit:
git bisect bad
O Git seleciona outro snapshot. Teste-o em vez de adivinhar:
python3 /opt/labex/quote-desk/check.py
Esta seleção passa com status 0. Registre essa observação:
git bisect good
O Git reduz o intervalo novamente. Você viu como cada resultado remove parte do espaço de busca. Para praticar o caminho automático a partir dos mesmos limites originais, saia primeiro desta busca incompleta. bisect reset limpa o estado da busca e retorna à branch e à revisão em que ela começou; ele não desfaz commits:
git bisect reset
git branch --show-current
Espere main. Se classificar uma versão incorretamente durante a prática, esse mesmo reset e um novo início permitem repetir usando os resultados reais do teste, sem descartar arquivos.
Deixe o Teste Conduzir a Busca
Comece novamente e forneça a bisect run o mesmo comando completo de teste. O Git usa cada status de saída nativo para escolher automaticamente entre correto e incorreto:
git bisect start incident-tip known-good
git bisect run python3 /opt/labex/quote-desk/check.py
Espere várias execuções do teste e uma linha terminando em is the first bad commit. O próprio comando de busca termina com status 0 quando encontra o limite com sucesso, embora alguns testes individuais de orçamento tenham falhado. Os IDs dos commits podem ser diferentes.
A referência bisect/bad do Git aponta para o primeiro commit incorreto identificado. O HEAD atual ainda pode ser a última versão correta testada; não suponha que ele seja o resultado relatado. Leia o patch do candidato real. show seleciona esse commit e seu patch; -- separa o caminho do arquivo:
git --no-pager show bisect/bad -- discounts.txt
A porcentagem de FRIEND10 mudou de 10 para 1. Confira os dois lados usando o teste externo. Um ^ no final seleciona o primeiro pai direto de um commit, portanto bisect/bad^ é a versão imediatamente anterior ao candidato, não um intervalo inteiro:
python3 /opt/labex/quote-desk/check.py --revision bisect/bad
python3 /opt/labex/quote-desk/check.py --revision bisect/bad^
Espere que o candidato falhe com status 1 e seu pai passe com status 0. Os valores e o comportamento real concordam. Deixe a busca concluída aberta para este ponto de verificação; a seguir, você voltará à loja atual antes de editar.
Corrija a Loja Atual e Entregue o Orçamento
Nesta etapa, saia da busca histórica, registre uma correção com um único objetivo na branch atual e entregue um orçamento completo sem perder produtos ou informações de retirada posteriores.
Permaneça em Terminal, em /home/labex/project/quote-desk/shop. Volte à branch original usando o reset de busca ensinado:
git bisect reset
git branch --show-current
git --no-pager log -1 --oneline --decorate
git status --short
Espere main, a ponta recebida marcada por incident-tip e nenhuma saída de arquivos alterados. A opção de log -1 limita a saída ao commit mais recente. Não corrija uma versão histórica destacada nem substitua a loja inteira por known-good: o trabalho posterior válido pertence ao resultado.
Leia o pequeno arquivo de ofertas e os detalhes atuais que você deve preservar:
cat discounts.txt
cat welcome.txt pickup.txt care.txt
cat catalog.json
A árvore atual inclui o Trail pin, a nova mensagem de boas-vindas e retirada no sábado até 16:00. Apenas a porcentagem de FRIEND10 está errada. O arquivo de ofertas contém uma configuração CODE=integer-percent por linha; TRAIL15 continua 15 e STUDENT5 continua 5.
Substitua apenas este pequeno arquivo. printf exibe valores conforme um formato: %s significa texto e \n adiciona uma quebra de linha após cada valor fornecido. As aspas simples preservam o texto literal. > grava a saída no arquivo nomeado, substituindo apenas esse arquivo:
printf '%s\n' 'FRIEND10=10' 'TRAIL15=15' 'STUDENT5=5' > discounts.txt
Revise a correção real. Um diff simples compara os arquivos de trabalho com o índice, a área de preparação do Git:
git --no-pager diff -- discounts.txt
Espere apenas FRIEND10 mudando de 1 de volta para 10. Configure uma identidade de commit local ao repositório antes de registrar a correção. --local evita configuração global; as aspas mantêm um nome com espaços como um único valor. Estes exemplos fictícios podem ser substituídos:
git config --local user.name "Little Pine Maintainer"
git config --local user.email "maintainer@little-pine.example"
Prepare esse arquivo com add. Inspecione o patch preparado com --cached, que compara o índice com o commit atual:
git add discounts.txt
git --no-pager diff --cached -- discounts.txt
Registre a correção com um único objetivo em um commit. -m fornece diretamente uma mensagem significativa:
git commit -m "Restore the promised FRIEND10 discount"
Compare com a ponta recebida fixa. Este é um novo commit de correção, que mantém todos os commits originais em vez de reescrever o histórico:
git --no-pager diff incident-tip HEAD
git --no-pager log -2 --oneline --decorate
git status --short
Espere apenas a correção da porcentagem, sua correção imediatamente após incident-tip e um estado rastreado limpo. A mensagem exata e os valores de autor não são o critério de sucesso.
Execute o teste preparado no programa atual real:
python3 /opt/labex/quote-desk/check.py
Todos os casos agora passam com status 0. Gere o orçamento do cliente:
python3 quote.py ../orders/gift.order
Espere a descrição atual da caneca e a mensagem de boas-vindas, quantidade 3, FRIEND10, subtotal EUR 48.00, desconto EUR 4.80, total EUR 43.20 e retirada atual até sábado às 16:00.
Entregue essa saída real no diretório quotes preparado. Como ensinado, > salva stdout neste arquivo nomeado; ele não altera o pedido nem o programa:
python3 quote.py ../orders/gift.order > ../quotes/mug-gift.txt
cat ../quotes/mug-gift.txt
Leia o orçamento salvo completo, não apenas seu nome de arquivo. O arquivo é o resultado utilizável pelo cliente, enquanto o commit torna a correção repetível.
Confira o pedido normal e o produto posterior, que devem permanecer utilizáveis:
python3 quote.py ../orders/plain.order
python3 quote.py ../orders/new-item.order
A caneca sem desconto continua EUR 16.00. Dois Trail pins com STUDENT5 têm subtotal EUR 10.00, desconto EUR 0.50 e total EUR 9.50. Ambos mantêm os detalhes atuais de boas-vindas e retirada. O ponto de verificação observa o commit atual real, a árvore completa preservada, o comportamento do limite histórico e o orçamento entregue; ele não avalia uma transcrição de comandos nem uma palavra-chave da mensagem.
Resumo
Você usou pedidos normais e incorretos para definir um teste de negócio, classificou versões históricas manualmente e automatizou a mesma busca com Git bisect. Você distinguiu a referência do primeiro commit incorreto de HEAD, verificou o candidato e seu pai, voltou à main e registrou uma correção com um único objetivo sem perder atualizações posteriores da loja. O cliente recebeu um orçamento completo e correto.
O desafio independente muda o cupom, o pedido do cliente e a posição da falha, usando o mesmo programa fornecido, a mesma política e o mesmo formato de teste. Escolha com base nas evidências reais em vez de copiar um deslocamento de commit.



