Setup and Config
Getting and Creating Projects
Basic Snapshotting
Branching and Merging
Sharing and Updating Projects
Inspection and Comparison
Patching
Debugging
External Systems
Server Admin
Guides
- gitattributes
- Command-line interface conventions
- Everyday Git
- Frequently Asked Questions (FAQ)
- Glossary
- Hooks
- gitignore
- gitmodules
- Revisions
- Submodules
- Tutorial
- Workflows
- All guides...
Administration
Plumbing Commands
- 2.44.1 → 2.46.2 no changes
- 2.44.0 02/23/24
- 2.43.3 → 2.43.5 no changes
- 2.43.2 02/13/24
- 2.43.1 02/09/24
- 2.43.0 11/20/23
- 2.42.1 → 2.42.3 no changes
- 2.42.0 08/21/23
- 2.29.1 → 2.41.2 no changes
- 2.29.0 10/19/20
- 2.25.1 → 2.28.1 no changes
- 2.25.0 01/13/20
- 2.18.1 → 2.24.4 no changes
- 2.18.0 06/21/18
- 2.17.0 → 2.17.6 no changes
- 2.16.6 12/06/19
- 2.14.6 → 2.15.4 no changes
- 2.13.7 05/22/18
- 2.12.5 no changes
- 2.11.4 09/22/17
- 2.10.5 no changes
- 2.9.5 07/30/17
- 2.8.6 no changes
- 2.7.6 07/30/17
- 2.6.7 05/05/17
- 2.2.3 → 2.5.6 no changes
- 2.1.4 12/17/14
- 2.0.5 12/17/14
DESCRIÇÃO
O comando assume vários subcomandos das diferentes opções dependendo do subcomando:
git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...] git bisect (bad|new|<term-new>) [<rev>] git bisect (good|old|<term-old>) [<rev>...] git bisect terms [--term-(good|old) | --term-(bad|new)] git bisect skip [(<rev>|<range>)...] git bisect reset [<commit>] git bisect (visualize|view) git bisect replay <logfile> git bisect log git bisect run <cmd> [<arg>...] git bisect help
Este comando utiliza um algoritmo de pesquisa binária para descobrir qual o commit no histórico do seu projeto introduziu um "bug" (problema). Você o utiliza informando primeiro a um commit "bad" (ruim) que é informado por conter o bug e um commit "good" (bom) informado antes da introdução do bug. Então o comando git bisect
seleciona um commit entre estes dois pontos extremos e pergunta se o commit selecionado é "bom" ou "ruim". Continua estreitando o intervalo até encontrar o commit exato responsável pela introdução da alteração.
De fato, o comando git bisect
pode ser utilizado para encontrar o commit que alterou qualquer propriedade do seu projeto; um commit que corrigiu um problema ou um commit que fez com que o desempenho de um benchmark melhorasse por exemplo. Para dar apoio a nesta utilização mais genérica, os termos "old" (antigo) e "new" (novo) podem ser utilizados no lugar de "good" (bom) e "bad" (ruim), ou escolha os seus próprios termos. Consulte a seção "Termos alternativos" abaixo para obter mais informações.
Comandos "bisect" básicos : start
(começar), bad
(ruim), good
(bom)
Como exemplo, suponha que você esteja tentando encontrar um commit que estragou um recurso que funcionava na versão v2.6.13-rc2
do seu projeto. Você começa uma seção "besect" como demonstrado abaixo:
$ git bisect start $ git bisect bad # A versão atual está ruim $ git bisect good v2.6.13-rc2 # v2.6.13-rc2 é conhecido por estar bom
Uma vez que você tenha utilizado pelo menos um commit ruim e um commit bom, o comando git bisect
seleciona um commit no meio deste intervalo do histórico, faz a averiguação e produz algo por exemplo:
Bisecting: 675 revisões deixadas para testar depois disso (aproximadamente 10 passos)
Agora você deve compilar a versão com check-out e testá-la. Caso esta versão funcione corretamente, digite
$ git bisect good
Se essa versão estiver quebrada, digite
$ git bisect bad
Então o comando git bisect
irá responder algo como
Bisecting: 337 revisões deixadas para testar depois disso (aproximadamente 9 passos)
Continue repetindo o processo: compile a árvore, teste-a e dependendo se ela for boa ou ruim, execute o comando git bisect good
ou git bisect bad
para solicitar o próximo commit que precisa ser testado.
Eventualmente, não haverá mais revisões a serem inspecionadas e o comando exibirá uma descrição do primeiro commit ruim. A referência refs/bisect/bad
será deixada apontando para o commit.
Bisect reset
Para limpar a condição geral bisseção e retornar ao HEAD
original, execute o seguinte comando:
$ git bisect reset
É predefinido que isso retornará a sua árvore para o commit que foi verificado antes do comando git bisect start
. (Um novo git bisect start
também fará isso, já que ele limpa o antigo estado de bisseção.)
Com um argumento opcional, você pode retornar para um commit diferente:
$ git bisect reset <commit>
Por exemplo, git bisect reset bisect/bad
irá verificar a primeira revisão ruim enquanto o git bisect reset HEAD
deixará você no commit atual da bisseção evitando a alternância para outros commits.
Termos alternativos
Às vezes, você não está procurando por um commit que introduziu um problema, mas sim um commit que causou uma alteração "antiga" entre alguma condição "nova". Você pode estar procurando por um commit que introduziu uma correção em específico por exemplo. Ou você pode estar procurando o primeiro commit onde os nomes dos arquivos do código-fonte foram finalmente convertidos para o padrão de nomes da sua empresa. Ou algo assim.
Nesses casos, pode ser muito confuso utilizar as opções "good" e "bad" para se referir a "condição antes da mudança" e "a condição após a mudança". Portanto, você pode utilizar os termos "old" e "new" respectivamente, no lugar de "good" e "bad". (Observe que não é possível misturar "good" e "bad" com "old" e "new" numa única sessão.)
Neste uso mais geral, você utiliza o comando git bisect
com um commit "new" que tem alguma propriedade e um commit "old" que não tem nenhuma. Cada vez que o comando git bisect
faz a verificação de um commit, você testa se o commit tem a propriedade. Em caso afirmativo, marque o commit como "new"; Caso contrário, marque-o como "old". Quando a bisseção tiver sido concluída, o comando git bisect
informará qual o commit que introduziu a propriedade.
Para utilizar "old" e "new" em vez de "good" e "bad", você deve executar git bisect start
sem nenhum commit e depois executar os seguintes comandos para adicionar os commits:
git bisect old [<rev>]
para indicar que um commit foi feito antes da alteração solicitada, ou
git bisect new [<rev>...]
para indicar que foi depois.
Para receber um lembrete dos termos utilizados no momento, utilize
git bisect terms
You can get just the old term with git bisect terms --term-old
or git bisect terms --term-good
; git bisect terms --term-new
and git bisect terms --term-bad
can be used to learn how to call the commits more recent than the sought change.
Caso queira utilizar os seus próprios termos em vez de "bad"/"good" ou "new"/"old", escolha qualquer nome que quiser (exceto os subcomandos bisect já existentes como reset
, start
, …) iniciando uma bisseção utilizando
git bisect start --term-old <termo-antigo> --term-new <novo-termo>
Caso esteja procurando por um commit que introduziu uma regressão ao desempenho, poderá utilizar por exemplo
git bisect start --term-old fast --term-new slow
Ou caso esteja procurando o commit que corrigiu um problema, você pode usar
git bisect start --term-new fixed --term-old broken
Então, utilize git bisect <termo-antigo>
e git bisect <novo-termo>
em vez de git bisect good
e git bisect bad
para marcar os commits.
Bisect visualize/observe
Para ver os suspeitos restantes no gitk, utilize o seguinte comando durante o processo de bisseção (o view
do subcomando pode ser utilizado como uma alternativa ao visualize
):
$ git bisect visualize
O Git detecta um ambiente gráfico através de várias variáveis de ambiente: DISPLAY
, que é definido em ambientes X Window System nos sistemas Unix. SESSIONNAME
, que é definido no Cygwin nas sessões de desktop interativas. MSYSTEM
, que é definido no Msys2 e o Git para Windows. SECURITYSESSIONID
, que pode ser definido no macOS nas sessões de ambiente de trabalho interativas.
O git log será usado caso nenhuma destas variável de ambiente sejam definidas. Tamém é possível usar as opções de linha de comando como -p
e --stat
.
$ git bisect visualize --stat
Bisect log e bisect replay
Depois de ter marcado as revisões como boas ou ruins, emita o seguinte comando para exibir o que foi feito até agora:
$ git bisect log
Caso descubra que cometeu um erro ao especificar a condição de uma revisão, é possível salvar o arquivo gerado num arquivo, editá-lo para remover as entradas que estiverem incorretas e em seguida, utilizar os seguintes comandos para corrigir a condição de corrigido:
$ git bisect reset $ git bisect replay that-file
Evitando o teste de um commit
Se no meio de uma sessão bisect, você sabe que a revisão sugerida não é boa para testar (ela falha em construir e você sabe que a falha não tem nada a ver com o bug que você está procurando por exemplo), é possível selecionar manualmente um commit próximo e testá-lo em vez disso.
Por exemplo:
$ git bisect good/bad # a rodada anterior estava boa ou ruim. Bisecting: 337 revisions left to test after this (roughly 9 steps) $ git bisect visualize # oops, isso não foi interessante. $ git reset --hard HEAD~3 # tente 3 revisões anteriores # ao que foi sugerido
Em seguida, compile, teste a revisão escolhida e depois marque a revisão da maneira usual como boa ou ruim.
Bisect skip
Em vez de escolher um commit próximo, é possível pedir ao Git para fazer isso por você, utilizando o comando:
$ git bisect skip # A versão atual não pode ser testada
No entanto, caso você pule um commit adjacente ao que você está procurando, o Git não saberá exatamente qual destes commits foi o primeiro que estava ruim.
É possível Você também pular um intervalo de commits em vez de apenas um, utilizando a notação do intervalo. Por exemplo:
$ git bisect skip v2.5..v2.6
Isso diz ao processo "bisect" que nenhum commit após a versão v2.5
e até a versão v2.6
, deve ser testada.
Observe que, caso você também queira pular o primeiro commit do intervalo, utilize o seguinte comando:
$ git bisect skip v2.5 v2.5..v2.6
Informa ao processo "bisect" que os commits entre as versões v2.5
e v2.6
(inclusive) devem ser ignorados.
Reduza a bisseção informando mais parâmetros para o início do bisect
É possível reduzir ainda mais a quantidade de tentativas caso saiba qual parte da árvore está envolvida no problema que está sendo rastreado, especificando parâmetros de pathpec ao usar o comando bisect start
:
$ git bisect start -- arch/i386 include/asm-i386
Caso saiba de antemão se há mais de um commit bom, é possível restringir o espaço do "bisect" ao informar todos os commits bons imediatamente após o commit com problema quando utilizar o comando bisect start
:
$ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 -- # v2.6.20-rc6 é ruim # v2.6.20-rc4 é v2.6.20-rc1 está bom
Bisect run
Caso tenha um script que possa dizer se o código-fonte atual é bom ou ruim, é possível fazer o "bisect" utilize o seguinte comando:
$ git bisect run meu_script opções
Observe que o script (meu_script
no exemplo acima) deve encerrar com o código 0 caso o código-fonte atual seja bom/antigo e encerrar com um código entre 1 e 127 (inclusive), exceto 125, caso o código-fonte atual seja ruim/novo.
Qualquer outro código gerado interromperá o processo bisect. Deve ser observado que um programa que encerra com exit (-1)
deixa um $? = 255, (consulte a página do manual exit(3)), pois o valor é cortado com & 0377
.
O código especial 125 da saída deve ser utilizado quando o código-fonte atual não puder ser testado. Caso o script encerre com este código, a revisão atual será ignorada (consulte o comando git bisect skip
acima). O 125 foi selecionado como o maior valor a ser utilizado para esta finalidade, pois 126 e 127 são utilizandos pelos shells POSIX para sinalizar uma condição de erro específica (127 é utilizado para o comando não encontrado, 126 é para o comando que foi encontrado, mas não é executável - estes detalhes não são importantes, pois são erros normais do script, no que diz respeito ao comando bisect run
).
Muitas vezes você pode achar que durante uma sessão bisect você queira ter alterações temporárias (s/#define DEBUG 0/#define DEBUG 1/
ao cabeçalho de um arquivo, ou "a revisão que não tem este commit e precisa que esta correção seja aplicada como um quebra galho que seja irrelevante para esta bisseção por exemplo") aplicada à revisão que está sendo testada.
Para lidar com essa situação, depois que o comando interno git bisect encontrar a próxima revisão que será testada, o script poderá aplicar a correção antes da compilação, executar o teste real, e depois, decidir se a revisão (possivelmente com a correção necessária) passou no teste, em seguida, retorna a árvore para o estado original. Finalmente, o script deve encerrar com a condição real do teste permitindo que o loop do comando git bisect run
determine o resultado final da sessão bisect.
OPÇÕES
- --no-checkout
-
Não faça o "checkout" da nova árvore de trabalho em cada iteração do processo de bissecção. Em vez disso, basta atualizar a referência chamada
BISECT_HEAD
para que ela aponte para o commit que deverá ser testado.Essa opção pode ser útil quando o teste que você executaria em cada etapa não exigir uma árvore com check-out.
Caso o repositório seja simples, assume-se a opção
--no-checkout
. - --first-parent
-
Siga apenas o primeiro commit ao ver a mesclagem de um commit.
Durante a detecção das regressões introduzidas através da mesclagem de um ramo o commit mesclado será identificado como uma introdução do bug e os seus ancestrais serão ignorados.
Esta opção é útil para evitar falsos positivos quando um ramo que foi mesclado tenham commits quebrados ou que não possam ser construídos, porém a mesclagem em si foi OK.
EXEMPLOS
-
Faça o bisect automaticamente uma construção quebrada entre v1.2 e HEAD:
$ git bisect start HEAD v1.2 -- # HEAD está ruim, v1.2 está bom $ git bisect run make # "make" compila o app $ git bisect reset # encerra a seção bisect
-
Faça o bisect automaticamente num teste que falhou entre a
origin
(origem) e oHEAD
:$ git bisect start HEAD origin -- # HEAD está ruim, origin está bom $ git bisect run make test # "make test" compila e testa $ git bisect reset # encerra a seção bisect
-
Faça o bisect automaticamente num teste quebrado:
$ cat ~/test.sh #!/bin/sh make || exit 125 # ignora as construções quebradas ~/check_test_case.sh # será que o exemplo passa? $ git bisect start HEAD HEAD~10 -- # o culpado está entre os últimos 10 $ git bisect run ~/test.sh $ git bisect reset # encerra a seção bisect
Aqui utilizamos um script
test.sh
. Neste scriipt, caso omake
falhe, nós ignoramos o commit atual. O arquivocheck_test_case.sh
deve encerrar comexit 0
se o cenário de teste for aprovado, caso contrário,exit 1
.É mais seguro se os arquivos
test.sh
echeck_test_case.sh
estiverem fora do repositório para evitar interações entre os processosbisect
,make
,test
e os scripts. -
Faça o bisect automaticamente com alterações temporárias (hot-fix):
$ cat ~/test.sh #!/bin/sh # faz ajustes na árvore de trabalho ao mesclar # a solução do problema no ramo e tenta compilá-lo if git merge --no-commit --no-ff hot-fix && make then # executa testes específicos no projeto e informa a sua condição atual ~/check_test_case.sh status=$? else # diga a quem requisitou que isso não pode ser testado status=125 fi # desfaça o ajuste para permitir uma alteração limpa para o próximo commit git reset --hard # controle de retorno existir $status
São aplicadas alterações de um hotfix para ramificação antes de cada teste, caso o seu ambiente de construção ou teste tenha sido alterado para que as revisões mais antigas precisem de uma correção que as mais recentes já tenham por exemplo. (Certifique-se que o hot-fix do ramo tenha base num commit que está contida em todos as revisões que você esteja fazendo o bisect, para que a mesclagem não realize muitos resgates ou utilize o comando
git cherry-pick
em vez dogit merge
. ) -
Faça o bisect automaticamente num teste quebrado:
$ git bisect start HEAD HEAD~10 -- # o culpado está entre os últimos 10 $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh" $ git bisect reset # encerra a seção bisect
Isso exibe o que você pode fazer sem executar um script caso escreva o teste numa única linha.
-
Localize uma boa região do grafo dos objetos num repositório que foi danificado
$ git bisect start HEAD <known-good-commit> [ <boundary-commit> ... ] --no-checkout $ git bisect run sh -c ' GOOD=$(git for-each-ref "--format=%(objectname)" refs/bisect/good-*) && git rev-list --objects BISECT_HEAD --not $GOOD >tmp.$$ && git pack-objects --stdout >/dev/null <tmp.$$ rc=$? rm -f tmp.$$ test $rc = 0' $ git bisect reset # encerra a seção bisect
Neste caso, quando git bisect run encerra, o bisect/bad (ruim) irá apontar para um commit que tenha pelo menos uma origem cujo grafo seja completamente cruzado no sentido requerido pelo comando git pack objects.
-
Procure por uma correção em vez de uma regressão no código
$ git bisect start $ git bisect new HEAD # o commit atual é marcado como novo $ git bisect old HEAD~10 # o décimo commit a partir de agora é marcado como antigo
ou:
$ git bisect start --term-old broken --term-new fixed $ git bisect fixed $ git bisect broken HEAD~10
GIT
Parte do conjunto git[1]