-
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
3.1 Ramificação (Branching) no Git - Branches em Poucas Palavras
Quase todos os VCSs têm alguma forma de suporte à ramificação (branching). Branching (ramificação) significa que você diverge da linha principal de desenvolvimento e continua a fazer o trabalho sem mexer nessa linha principal. Em muitas ferramentas de VCS, este é um processo um tanto custoso, muitas vezes exigindo que você crie uma nova cópia do diretório de código-fonte, o que pode levar muito tempo em projetos grandes.
Algumas pessoas se referem ao modelo de ramificação do Git como seu “recurso matador (killer feature)”, e ele certamente destaca o Git na comunidade de VCS. Por que é tão especial? A maneira como o Git ramifica é incrivelmente leve, tornando as operações de ramificação quase instantâneas, e alternar entre as ramificações (branches) geralmente é igualmente rápido. Ao contrário de muitos outros VCSs, o Git incentiva fluxos de trabalho que ramificam (branch) e mesclam (merge) frequentemente, até várias vezes ao dia. Compreender e dominar esse recurso fornece a você uma ferramenta poderosa e única, e pode mudar completamente a maneira como você desenvolve.
Branches em Poucas Palavras
Para realmente entender a maneira como o Git faz ramificação (branching), precisamos dar um passo atrás e examinar como o Git armazena seus dados.
Como você deve se lembrar do O que é Git?, o Git não armazena dados como uma série de conjuntos de alterações (changesets) ou diferenças, mas sim como uma série de snapshots (instantâneos).
Quando você faz um commit, o Git armazena um objeto de commit que contém um ponteiro para o snapshot do conteúdo que você preparou (staged). Este objeto também contém o nome e o endereço de e-mail do autor, a mensagem que você digitou e ponteiros para o commit ou commits que vieram diretamente antes deste commit (seu pai ou pais): zero pais para o commit inicial, um pai para um commit normal e vários pais para um commit que resulta de uma mesclagem (merge) de dois ou mais branches.
Para visualizar isso, vamos assumir que você tem um diretório contendo três arquivos, e você prepara (stage) todos eles e faz o commit. Preparar (staging) os arquivos calcula um checksum para cada um (o hash SHA-1 que mencionamos em O que é Git?), armazena essa versão do arquivo no repositório Git (o Git se refere a eles como blobs) e adiciona esse checksum à área de preparação (staging area):
$ git add README test.rb LICENSE
$ git commit -m 'Initial commit'
Quando você cria o commit executando git commit, o Git calcula o checksum de cada subdiretório (neste caso, apenas o diretório raiz do projeto) e os armazena como um objeto de árvore (tree) no repositório Git.
O Git então cria um objeto de commit que tem os metadados e um ponteiro para a árvore do projeto raiz para que ele possa recriar aquele snapshot quando necessário.
Seu repositório Git agora contém cinco objetos: três blobs (cada um representando o conteúdo de um dos três arquivos), uma árvore (tree) que lista o conteúdo do diretório e especifica quais nomes de arquivo são armazenados como quais blobs, e um commit com o ponteiro para essa árvore raiz e todos os metadados do commit.
Se você fizer algumas alterações e fizer commit novamente, o próximo commit armazenará um ponteiro para o commit que veio imediatamente antes dele.
Um branch no Git é simplesmente um ponteiro móvel e leve para um desses commits.
O nome do branch padrão no Git é master.
À medida que você começa a fazer commits, você recebe um branch master que aponta para o último commit que você fez.
Toda vez que você faz um commit, o ponteiro do branch master avança automaticamente.
|
Note
|
O branch “master” no Git não é um branch especial.
É exatamente como qualquer outro branch.
A única razão pela qual quase todo repositório tem um é que o comando |
Criando um Novo Branch
O que acontece quando você cria um novo branch?
Bem, fazer isso cria um novo ponteiro para você mover por aí.
Digamos que você queira criar um novo branch chamado testing.
Você faz isso com o comando git branch:
$ git branch testing
Isso cria um novo ponteiro para o mesmo commit em que você está no momento.
Como o Git sabe em qual branch você está no momento?
Ele mantém um ponteiro especial chamado HEAD.
Observe que isso é muito diferente do conceito de HEAD em outros VCSs aos quais você pode estar acostumado, como Subversion ou CVS.
No Git, este é um ponteiro para o branch local em que você está no momento.
Neste caso, você ainda está no master.
O comando git branch apenas criou um novo branch — ele não mudou para aquele branch.
Você pode ver isso facilmente executando um comando simples git log que mostra para onde os ponteiros de branch estão apontando.
Esta opção é chamada --decorate.
$ git log --oneline --decorate
f30ab (HEAD -> master, testing) Add feature #32 - ability to add new formats to the central interface
34ac2 Fix bug #1328 - stack overflow under certain conditions
98ca9 Initial commit
Você pode ver os branches master e testing que estão bem ali ao lado do commit f30ab.
Mudando de Branches
Para mudar para um branch existente, você executa o comando git checkout.
Vamos mudar para o novo branch testing:
$ git checkout testing
Isso move o HEAD para apontar para o branch testing.
Qual o significado disso? Bem, vamos fazer outro commit:
$ vim test.rb
$ git commit -a -m 'Make a change'
Isso é interessante, porque agora o seu branch testing avançou, mas o seu branch master ainda aponta para o commit em que você estava quando executou git checkout para mudar de branch.
Vamos voltar para o branch master:
$ git checkout master
|
Note
|
git log não mostra todos os branches o tempo todo
Se você executasse O branch não desapareceu; o Git apenas não sabe que você está interessado naquele branch e está tentando mostrar o que ele acha que você está interessado.
Em outras palavras, por padrão, o Para mostrar o histórico de commits do branch desejado, você deve especificá-lo explicitamente: |
Aquele comando fez duas coisas.
Ele moveu o ponteiro HEAD de volta para apontar para o branch master, e reverteu os arquivos no seu diretório de trabalho de volta para o snapshot para o qual o master aponta.
Isso também significa que as alterações feitas a partir deste ponto divergirão de uma versão anterior do projeto.
Ele essencialmente retrocede (rewinds) o trabalho que você fez no seu branch testing para que você possa seguir em uma direção diferente.
|
Note
|
Mudar de branch altera os arquivos no seu diretório de trabalho
É importante observar que quando você muda de branch no Git, os arquivos no seu diretório de trabalho serão alterados. Se você mudar para um branch mais antigo, seu diretório de trabalho será revertido para ficar como na última vez em que você fez commit naquele branch. Se o Git não conseguir fazer isso de forma limpa (cleanly), ele não permitirá a mudança. |
Vamos fazer algumas alterações e commitar novamente:
$ vim test.rb
$ git commit -a -m 'Make other changes'
Agora o histórico do seu projeto divergiu (veja Histórico divergente).
Você criou e mudou para um branch, fez algum trabalho nele, e então mudou de volta para o seu branch principal e fez outro trabalho.
Ambas as alterações estão isoladas em branches separados: você pode alternar entre os branches e mesclá-los quando estiver pronto.
E você fez tudo isso com simples comandos branch, checkout e commit.
Você também pode ver isso facilmente com o comando git log.
Se você executar git log --oneline --decorate --graph --all ele imprimirá o histórico de seus commits, mostrando onde estão os ponteiros do seu branch e como o seu histórico divergiu.
$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) Make other changes
| * 87ab2 (testing) Make a change
|/
* f30ab Add feature #32 - ability to add new formats to the central interface
* 34ac2 Fix bug #1328 - stack overflow under certain conditions
* 98ca9 Initial commit of my project
Como um branch no Git é na verdade um arquivo simples que contém o checksum SHA-1 de 40 caracteres do commit para o qual ele aponta, os branches são baratos de criar e destruir. Criar um novo branch é tão rápido e simples quanto gravar 41 bytes em um arquivo (40 caracteres e uma nova linha).
Isso está em nítido contraste com a maneira como a maioria das ferramentas de VCS mais antigas ramificam (branch), o que envolve copiar todos os arquivos do projeto para um segundo diretório. Isso pode levar alguns segundos ou até minutos, dependendo do tamanho do projeto, enquanto que no Git o processo é sempre instantâneo. Além disso, como estamos registrando os pais quando fazemos o commit, encontrar uma base de mesclagem (merge base) adequada para a mesclagem é feito automaticamente para nós e geralmente é muito fácil de fazer. Esses recursos ajudam a incentivar os desenvolvedores a criar e usar branches com frequência.
Vamos ver por que você deve fazer isso.
|
Note
|
Criando um novo branch e mudando para ele ao mesmo tempo
É comum criar um novo branch e querer mudar para ele ao mesmo tempo — isso pode ser feito em uma única operação com |
|
Note
|
A partir do Git versão 2.23 em diante, você pode usar
|