-
1. Primeiros Passos
- 1.1 Sobre Controle de Versão
- 1.2 Uma Breve História do Git
- 1.3 O que é Git?
- 1.4 A Linha de Comando
- 1.5 Instalando o Git
- 1.6 Configuração inicial do Git
- 1.7 Obtendo Ajuda
- 1.8 Resumo
-
2. Fundamentos do Git
-
3. Ramificação (Branching) no Git
-
4. Git no Servidor
- 4.1 Os Protocolos
- 4.2 Colocando o Git em um Servidor
- 4.3 Gerando a sua Chave Pública SSH
- 4.4 Configurando o Servidor
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Opções de Hospedagem de Terceiros
- 4.10 Resumo
-
5. Git Distribuído
-
6. GitHub
-
7. Ferramentas do Git
- 7.1 Seleção de Revisão
- 7.2 Área de Stage Interativa
- 7.3 Fazendo Stash e Limpando
- 7.4 Assinando Seu Trabalho
- 7.5 Pesquisando (Searching)
- 7.6 Reescrevendo o Histórico
- 7.7 Reset Desmistificado
- 7.8 Merging Avançado
- 7.9 Rerere
- 7.10 Depurando com Git
- 7.11 Submódulos
- 7.12 Empacotando (Bundling)
- 7.13 Substituir (Replace)
- 7.14 Armazenamento de Credenciais
- 7.15 Resumo
-
8. Customizando o Git
- 8.1 Configuração do Git
- 8.2 Atributos do Git
- 8.3 Hooks do Git
- 8.4 Uma Política de Exemplo Imposta pelo Git
- 8.5 Resumo
-
9. Git e Outros Sistemas
- 9.1 Git como Cliente
- 9.2 Migrando para o Git
- 9.3 Resumo
-
10. Git Internals (Por Dentro do Git)
- 10.1 Encanamento e Porcelana (Plumbing and Porcelain)
- 10.2 Objetos do Git
- 10.3 Referências do Git
- 10.4 Arquivos de pacote (Packfiles)
- 10.5 Refspec
- 10.6 Protocolos de Transferência
- 10.7 Manutenção e Recuperação de Dados
- 10.8 Variáveis de Ambiente
- 10.9 Resumo
-
A1. Appendix A: O Git em Outros Ambientes
- A1.1 Interfaces Gráficas
- A1.2 Git no Visual Studio
- A1.3 Git no Visual Studio Code
- A1.4 Git no IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git no Sublime Text
- A1.6 Git no Bash
- A1.7 Git no Zsh
- A1.8 Git no PowerShell
- A1.9 Resumo
-
A2. Appendix B: Incorporando o Git nos seus Aplicativos
- A2.1 Linha de Comando do Git
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Appendix C: Comandos do Git
- A3.1 Configuração e Ajustes
- A3.2 Obtendo e Criando Projetos
- A3.3 Snapshots Básicos
- A3.4 Branches e Merges
- A3.5 Compartilhando e Atualizando Projetos
- A3.6 Inspeção e Comparação
- A3.7 Depuração
- A3.8 Patches
- A3.9 E-mail
- A3.10 Sistemas Externos
- A3.11 Administração
- A3.12 Comandos de Encanamento
7.10 Ferramentas do Git - Depurando com Git
Depurando com Git
Além de ser principalmente para controle de versão, o Git também fornece alguns comandos para ajudá-lo a depurar seus projetos de código-fonte. Como o Git foi projetado para lidar com quase qualquer tipo de conteúdo, essas ferramentas são bastante genéricas, mas muitas vezes podem ajudá-lo a caçar um bug ou culpado quando as coisas dão errado.
Anotação de Arquivo
Se você rastrear um bug no seu código e quiser saber quando ele foi introduzido e por que, a anotação de arquivo (file annotation) é frequentemente sua melhor ferramenta.
Ela mostra qual commit foi o último a modificar cada linha de qualquer arquivo.
Então, se você ver que um método no seu código está com bugs, você pode anotar o arquivo com git blame para determinar qual commit foi responsável pela introdução daquela linha.
O exemplo seguinte usa git blame para determinar qual commit e committer foi responsável pelas linhas no Makefile de nível superior do kernel do Linux e, além disso, usa a opção -L para restringir a saída da anotação às linhas 69 a 82 daquele arquivo:
$ git blame -L 69,82 Makefile
b8b0618cf6fab (Cheng Renquan 2009-05-26 16:03:07 +0800 69) ifeq ("$(origin V)", "command line")
b8b0618cf6fab (Cheng Renquan 2009-05-26 16:03:07 +0800 70) KBUILD_VERBOSE = $(V)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) ifndef KBUILD_VERBOSE
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) KBUILD_VERBOSE = 0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75)
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 76) ifeq ($(KBUILD_VERBOSE),1)
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 77) quiet =
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 78) Q =
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 79) else
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 80) quiet=quiet_
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 81) Q = @
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 82) endif
Note que o primeiro campo é o SHA-1 parcial do commit que modificou aquela linha por último.
Os próximos dois campos são valores extraídos daquele commit — o nome do autor e a data de autoria daquele commit — para que você possa ver facilmente quem modificou aquela linha e quando.
Depois disso vêm o número da linha e o conteúdo do arquivo.
Note também as linhas de commit ^1da177e4c3f4, onde o prefixo ^ designa linhas que foram introduzidas no commit inicial do repositório e permaneceram inalteradas desde então.
Isso é um pouco confuso, porque agora você já viu pelo menos três maneiras diferentes que o Git usa o ^ para modificar um SHA-1 de commit, mas é isso o que ele significa aqui.
Outra coisa legal sobre o Git é que ele não rastreia renomeações de arquivos explicitamente.
Ele grava os snapshots e depois tenta descobrir o que foi renomeado implicitamente, após o fato.
Uma das características interessantes disso é que você também pode pedir a ele para descobrir todos os tipos de movimento de código.
Se você passar -C para o git blame, o Git analisa o arquivo que você está anotando e tenta descobrir de onde os trechos de código nele originalmente vieram, caso tenham sido copiados de outro lugar.
Por exemplo, digamos que você está refatorando um arquivo chamado GITServerHandler.m em vários arquivos, um dos quais é GITPackUpload.m.
Anotando o GITPackUpload.m com a opção -C, você pode ver de onde originalmente vieram seções do código:
$ git blame -C -L 141,153 GITPackUpload.m
f344f58d GITServerHandler.m (Scott 2009-01-04 141)
f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) gatherObjectShasFromC
f344f58d GITServerHandler.m (Scott 2009-01-04 143) {
70befddd GITServerHandler.m (Scott 2009-03-22 144) //NSLog(@"GATHER COMMI
ad11ac80 GITPackUpload.m (Scott 2009-03-24 145)
ad11ac80 GITPackUpload.m (Scott 2009-03-24 146) NSString *parentSha;
ad11ac80 GITPackUpload.m (Scott 2009-03-24 147) GITCommit *commit = [g
ad11ac80 GITPackUpload.m (Scott 2009-03-24 148)
ad11ac80 GITPackUpload.m (Scott 2009-03-24 149) //NSLog(@"GATHER COMMI
ad11ac80 GITPackUpload.m (Scott 2009-03-24 150)
56ef2caf GITServerHandler.m (Scott 2009-01-05 151) if(commit) {
56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb
56ef2caf GITServerHandler.m (Scott 2009-01-05 153)
Isso é realmente útil. Normalmente, você obtém como o commit original o commit onde você copiou o código para lá, porque essa é a primeira vez que você tocou nessas linhas neste arquivo. O Git diz qual foi o commit original em que você escreveu essas linhas, mesmo que isso tenha sido em outro arquivo.
Pesquisa Binária (Binary Search)
Anotar um arquivo ajuda se você sabe, de início, onde o problema está.
Se você não sabe o que está quebrando, e houveram dezenas ou centenas de commits desde o último estado em que você sabe que o código funcionou, você provavelmente vai recorrer ao git bisect por ajuda.
O comando bisect faz uma pesquisa binária por todo o seu histórico de commits para ajudá-lo a identificar, o mais rápido possível, qual commit introduziu um problema.
Digamos que você acabou de dar push de uma release do seu código para um ambiente de produção, e você está recebendo relatos de bugs sobre algo que não estava acontecendo no seu ambiente de desenvolvimento, e você não consegue imaginar por que o código está fazendo isso.
Você volta para o seu código e descobre que consegue reproduzir o problema, mas não consegue descobrir o que está dando errado.
Você pode fazer um bisect do código para descobrir.
Primeiro você roda git bisect start para dar o pontapé inicial, e depois você usa git bisect bad para dizer ao sistema que o commit atual no qual você está se encontra quebrado.
Então, você tem que informar ao bisect qual foi o último estado sabidamente bom, usando git bisect good <commit_bom>:
$ git bisect start
$ git bisect bad
$ git bisect good v1.0
Bisecting: 6 revisions left to test after this
[ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] Error handling on repo
O Git descobriu que houve cerca de 12 commits entre o commit que você marcou como o último commit bom (v1.0) e a atual versão ruim, e fez checkout daquele bem no meio para você.
A esta altura, você pode rodar o seu teste para ver se o problema existe na época deste commit.
Se ele existir, então ele foi introduzido em algum momento antes deste commit intermediário; se ele não existir, então o problema foi introduzido em algum momento após o commit intermediário.
Vê-se que não há nenhum problema aqui, e você conta isso para o Git digitando git bisect good e prossegue na sua jornada:
$ git bisect good
Bisecting: 3 revisions left to test after this
[b047b02ea83310a70fd603dc8cd7a6cd13d15c04] Secure this thing
Agora você está em um outro commit, bem no meio do caminho entre o que você testou por último e o seu commit ruim.
Você roda o teste novamente e constata que este commit está quebrado, então você informa isto ao Git usando git bisect bad:
$ git bisect bad
Bisecting: 1 revisions left to test after this
[f71ce38690acf49c1f3c9bea38e09d82a5ce6014] Drop exceptions table
Este commit está bom, e agora o Git tem toda a informação que ele precisa para determinar onde o problema foi introduzido. Ele te dá o SHA-1 do primeiro commit ruim (bad commit) e mostra algumas das informações do commit e quais arquivos foram modificados nesse commit, para que você possa descobrir o que aconteceu que possivelmente causou este bug:
$ git bisect good
b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit
commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04
Author: PJ Hyett <pjhyett@example.com>
Date: Tue Jan 27 14:48:32 2009 -0800
Secure this thing
:040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730
f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config
Quando você terminar, você deve rodar git bisect reset para resetar seu HEAD de volta para onde você estava antes de você ter começado, ou você vai terminar em um estado estranho:
$ git bisect reset
Esta é uma ferramenta poderosa que pode ajudar você a checar centenas de commits à procura de um bug introduzido, em minutos.
De fato, se você tiver um script que vai dar exit com 0 caso o projeto seja bom ou não-0 caso o projeto seja ruim, você consegue automatizar o git bisect completamente.
Primeiro, mais uma vez você tem que determinar o escopo do bisect informando os commits conhecidos bom (good) e ruim (bad).
Você pode fazer isso listando-os com o comando bisect start se quiser, primeiro o commit ruim e depois o bom:
$ git bisect start HEAD v1.0
$ git bisect run test-error.sh
Ao fazer isso o Git executa automaticamente o script test-error.sh a cada commit extraído até ele encontrar o primeiro que está com problema.
Você pode ainda, usar comandos, tais como, make ou make tests ou até mesmo um script qualquer para a execução automatizada dos testes.