-
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
8.1 Customizando o Git - Configuração do Git
Até agora, cobrimos os conceitos básicos de como o Git funciona e como usá-lo, e introduzimos uma série de ferramentas que o Git fornece para ajudá-lo a usá-lo de forma fácil e eficiente. Neste capítulo, veremos como você pode fazer o Git operar de uma maneira mais personalizada, introduzindo várias definições de configuração importantes e o sistema de ganchos (hooks). Com essas ferramentas, é fácil fazer com que o Git funcione exatamente da maneira que você, sua empresa ou seu grupo precisa.
Configuração do Git
Como você viu rapidamente no Primeiros Passos, é possível ajustar opções da configuração do Git através do comando git config.
E que uma das primeiras coisas que você fez com ele foi configurar o seu nome e endereço de email:
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
Neste momento você vai ficar sabendo de mais algumas opções bem interessantes e que também são passíveis de ajuste por essa via com vistas a customizar sua lida junto a esse Git.
Mas antes, uma rápida recapitulação: O Git lança mão de um conjunto de arquivos em que ficam retidas configurações a orientá-lo sobre perfis de comportamento para além do formato padrão, a fim de deixá-lo no jeito que você possa querer.
O primeiro lugar em que o Git procura esses valores é o arquivo [path]/etc/gitconfig do sistema, que contém configurações aplicadas a todos os usuários do sistema e a todos os seus repositórios.
Havendo que passar a opção --system ao git config, ele foca a ler e bem com na escrita com estrita destinação nas guisas deste arquivo em específico.
Em seguida, o Git procura o arquivo ~/.gitconfig (ou ~/.config/git/config), específico de cada usuário.
Você dita ao Git para ler e ali despontar na lide sobre ele com escritas por ali, de molde através das passagens concernentes à via d’opção pautada por --global.
Por fim, o Git procura valores no arquivo de configuração do diretório Git (.git/config) do repositório que você está usando no momento.
Esses valores são específicos desse único repositório e correspondem a passar a opção --local para git config.
Se você não especificar o nível com o qual deseja trabalhar, esse será o padrão.
Cada um desses “níveis” (sistema, global e local) sobrescreve valores do nível anterior; assim, por exemplo, os valores em .git/config prevalecem sobre os de [path]/etc/gitconfig.
|
Note
|
Os arquivos de configuração do Git são texto puro, portanto você também pode definir esses valores editando o arquivo manualmente e inserindo a sintaxe correta.
No entanto, em geral é mais fácil executar o comando |
Configurações Básicas de Cliente
As opções de configuração reconhecidas pelo Git se dividem em duas categorias: as do lado do cliente e as do lado do servidor. A maioria das opções fica no lado do cliente e configura suas preferências pessoais de trabalho. O Git oferece muitas opções de configuração, mas grande parte delas só é útil em casos extremos específicos; abordaremos aqui apenas as opções mais comuns e úteis. Para ver uma lista de todas as opções reconhecidas pela sua versão do Git, execute:
$ man git-config
Esse comando lista todas as opções disponíveis com bastante detalhe. Você também encontra esse material de referência em https://git-scm.com/docs/git-config.
|
Note
|
Para casos de uso avançados, consulte "Conditional includes" na documentação mencionada acima. |
core.editor
Por padrão, o Git usa o editor de texto que você definiu por meio de uma das variáveis de ambiente do shell, VISUAL ou EDITOR; se nenhuma estiver definida, usa o editor vi para criar e editar suas mensagens de commit e tag.
Para trocar esse padrão por outro editor, use a configuração core.editor:
$ git config --global core.editor emacs
Agora, independentemente do editor padrão definido no shell, o Git iniciará o Emacs para editar as mensagens.
commit.template
Se você definir esse valor como o caminho de um arquivo no sistema, o Git usará esse arquivo como mensagem inicial padrão ao criar um commit. A vantagem de criar um modelo de commit personalizado é poder usá-lo para lembrar a si mesmo (ou a outras pessoas) do formato e estilo adequados ao escrever uma mensagem de commit.
Por exemplo, considere um arquivo de modelo em ~/.gitmessage.txt com este conteúdo:
Subject line (try to keep under 50 characters)
Multi-line description of commit,
feel free to be detailed.
[Ticket: X]
Observe como esse modelo lembra o autor do commit de manter a linha de assunto curta (para beneficiar a saída de git log --oneline), acrescentar mais detalhes abaixo e mencionar o número de uma issue ou de um ticket do rastreador de bugs, caso exista.
Para instruir o Git a usá-lo como a mensagem padrão exibida no editor ao executar git commit, defina o valor de configuração commit.template:
$ git config --global commit.template ~/.gitmessage.txt
$ git commit
Então, ao fazer um commit, seu editor será aberto com uma mensagem provisória semelhante a esta:
Subject line (try to keep under 50 characters)
Multi-line description of commit,
feel free to be detailed.
[Ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C
Se sua equipe tem uma política para mensagens de commit, colocar no sistema um modelo dessa política e configurar o Git para usá-lo por padrão pode aumentar a probabilidade de ela ser seguida regularmente.
core.pager
Essa configuração determina qual paginador é usado quando o Git pagina a saída de comandos como log e diff.
Você pode defini-la como more ou como seu paginador preferido (o padrão é less), ou pode desativá-la definindo uma string vazia:
$ git config --global core.pager ''
Se você executar esse comando, o Git imprimirá toda a saída de todos os comandos, independentemente do comprimento.
user.signingkey
Se você cria tags anotadas e assinadas (como discutido em Assinando Seu Trabalho), definir sua chave de assinatura GPG na configuração simplifica o processo. Defina o ID da sua chave assim:
$ git config --global user.signingkey <gpg-key-id>
Agora você pode assinar tags sem precisar especificar sua chave toda vez que usar o comando git tag:
$ git tag -s <tag-name>
core.excludesfile
Você pode colocar padrões no arquivo .gitignore do projeto para que o Git não os veja como arquivos não rastreados nem tente adicioná-los ao stage ao executar git add, como discutido em Ignorando Arquivos.
No entanto, às vezes você deseja ignorar certos arquivos em todos os repositórios com os quais trabalha.
Se seu computador executa macOS, você provavelmente conhece os arquivos .DS_Store.
Se seu editor preferido é Emacs ou Vim, conhece nomes de arquivo que terminam em ~ ou .swp.
Essa configuração permite criar uma espécie de arquivo .gitignore global.
Se você criar um arquivo ~/.gitignore_global com este conteúdo:
*~
.*.swp
.DS_Store
…e executar git config --global core.excludesfile ~/.gitignore_global, o Git nunca mais o incomodará com esses arquivos.
help.autocorrect
Se você digitar um comando incorretamente, ele mostrará algo semelhante a isto:
$ git chekcout master
git: 'chekcout' is not a git command. See 'git --help'.
The most similar command is
checkout
O Git tenta, de maneira prestativa, descobrir o que você quis dizer, mas ainda se recusa a executar o comando.
Se você definir help.autocorrect como 1, o Git realmente executará o comando para você:
$ git chekcout master
WARNING: You called a Git command named 'chekcout', which does not exist.
Continuing under the assumption that you meant 'checkout'
in 0.1 seconds automatically...
Observe a menção a “0.1 seconds”.
Na verdade, help.autocorrect é um número inteiro que representa décimos de segundo.
Portanto, se você defini-lo como 50, o Git lhe dará 5 segundos para mudar de ideia antes de executar o comando corrigido automaticamente.
Cores no Git
O Git oferece suporte completo a saída colorida no terminal, o que facilita muito a análise visual rápida da saída dos comandos. Várias opções permitem ajustar as cores às suas preferências.
color.ui
O Git colore automaticamente a maior parte da saída, mas há uma configuração geral caso você não goste desse comportamento. Para desativar toda a saída colorida do Git no terminal, faça isto:
$ git config --global color.ui false
A configuração padrão é auto, que colore a saída quando ela vai diretamente para um terminal, mas omite os códigos de controle de cor quando a saída é redirecionada para um pipe ou arquivo.
Você também pode defini-la como always para ignorar a diferença entre terminais e pipes.
Raramente isso será desejável; na maioria dos cenários, se quiser códigos de cor na saída redirecionada, você pode passar a flag --color ao comando Git para forçar seu uso.
A configuração padrão quase sempre é a melhor opção.
color.*
Se quiser especificar com mais detalhes quais comandos recebem cores e de que maneira, o Git oferece configurações de cor específicas para cada comando.
Cada uma delas pode ser definida como true, false ou always:
color.branch color.diff color.interactive color.status
Além disso, cada uma possui subconfigurações que permitem definir cores específicas para partes da saída, caso você queira substituir cada cor. Por exemplo, para configurar as meta informações na sua saída do diff para o primeiro plano azul, fundo preto e texto em negrito, você pode executar:
$ git config --global color.diff.meta "blue black bold"
Você pode configurar a cor para qualquer um dos seguintes valores: normal, black, red, green, yellow, blue, magenta, cyan ou white.
Se você quiser um atributo como negrito no exemplo anterior, pode escolher entre bold, dim, ul (sublinhado), blink e reverse (troca o primeiro plano e o fundo).
Ferramentas Externas de Merge e Diff
Embora o Git tenha uma implementação interna de diff, que é o que temos mostrado neste livro, você pode configurar uma ferramenta externa em vez disso. Você também pode configurar uma ferramenta gráfica de resolução de conflito de merge em vez de ter que resolver conflitos manualmente. Vamos demonstrar a configuração da Perforce Visual Merge Tool (P4Merge) para fazer seus diffs e resoluções de merge, porque é uma ferramenta gráfica agradável e é gratuita.
Se você quiser experimentar isso, o P4Merge funciona em todas as principais plataformas, então você deve ser capaz de fazer isso.
Usaremos nomes de caminho nos exemplos que funcionam em sistemas macOS e Linux; para Windows, você terá que alterar /usr/local/bin para um caminho executável em seu ambiente.
Para começar, baixe o P4Merge da Perforce.
Em seguida, você configurará scripts wrapper externos para executar seus comandos.
Usaremos o caminho do macOS para o executável; em outros sistemas, será onde o seu binário p4merge está instalado.
Configure um script wrapper de merge chamado extMerge que chama o seu binário com todos os argumentos fornecidos:
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/p4merge.app/Contents/MacOS/p4merge $*
O wrapper diff verifica se sete argumentos são fornecidos e passa dois deles para o seu script de merge. Por padrão, o Git passa os seguintes argumentos para o programa diff:
path old-file old-hex old-mode new-file new-hex new-mode
Como você só deseja os argumentos old-file e new-file, você usa o script wrapper para passar os que precisa.
$ cat /usr/local/bin/extDiff
#!/bin/sh
[ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"
Você também precisa se certificar de que essas ferramentas são executáveis:
$ sudo chmod +x /usr/local/bin/extMerge
$ sudo chmod +x /usr/local/bin/extDiff
Agora você pode configurar seu arquivo de configuração para usar suas ferramentas personalizadas de resolução de merge e diff.
Isso exige várias configurações personalizadas: merge.tool para dizer ao Git qual estratégia usar, mergetool.<tool>.cmd para especificar como executar o comando, mergetool.<tool>.trustExitCode para dizer ao Git se o código de saída desse programa indica uma resolução de merge bem-sucedida ou não, e diff.external para dizer ao Git qual comando executar para diffs.
Então, você pode executar quatro comandos de configuração:
$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.extMerge.trustExitCode false
$ git config --global diff.external extDiff
ou você pode editar o seu arquivo ~/.gitconfig para adicionar estas linhas:
[merge]
tool = extMerge
[mergetool "extMerge"]
cmd = extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
trustExitCode = false
[diff]
external = extDiff
Depois que tudo isso estiver configurado, se você executar comandos de diff como este:
$ git diff 32d1776b1^ 32d1776b1
Em vez de obter a saída do diff na linha de comando, o Git inicia o P4Merge, que se parece com isto:
Se você tentar fazer o merge de duas branches e posteriormente tiver conflitos de merge, você pode executar o comando git mergetool; ele inicia o P4Merge para permitir que você resolva os conflitos através dessa ferramenta GUI.
A coisa boa sobre essa configuração de wrapper é que você pode alterar suas ferramentas de diff e merge facilmente.
Por exemplo, para alterar suas ferramentas extDiff e extMerge para executarem a ferramenta KDiff3 em vez disso, tudo o que você tem que fazer é editar o seu arquivo extMerge:
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*
Agora, o Git usará a ferramenta KDiff3 para a visualização de diffs e resolução de conflitos de merge.
O Git vem pré-configurado para usar várias outras ferramentas de resolução de conflitos sem que você precise configurar a configuração cmd. Para ver uma lista das ferramentas que ele suporta, tente o seguinte:
$ git mergetool --tool-help
'git mergetool --tool=<tool>' may be set to one of the following:
emerge
gvimdiff
gvimdiff2
opendiff
p4merge
vimdiff
vimdiff2
The following tools are valid, but not currently available:
araxis
bc3
codecompare
deltawalker
diffmerge
diffuse
ecmerge
kdiff3
meld
tkdiff
tortoisemerge
xxdiff
Some of the tools listed above only work in a windowed
environment. If run in a terminal-only session, they will fail.
Se você não estiver interessado em usar o KDiff3 para diff, mas sim usá-lo apenas para a resolução de conflitos de merge, e o comando kdiff3 estiver no seu caminho, então você pode executar:
$ git config --global merge.tool kdiff3
Se você executar isso em vez de configurar os arquivos extMerge e extDiff, o Git usará o KDiff3 para resolução de conflitos de merge e a ferramenta diff normal do Git para diffs.
Formatação e Espaço em Branco
Problemas de formatação e espaço em branco são alguns dos problemas mais frustrantes e sutis que muitos desenvolvedores enfrentam ao colaborar, especialmente em plataformas cruzadas. É muito fácil que patches ou outro trabalho colaborativo introduzam alterações sutis de espaço em branco porque os editores as introduzem silenciosamente, e se os seus arquivos tocarem em um sistema Windows, suas terminações de linha podem ser substituídas. O Git tem algumas opções de configuração para ajudar com esses problemas.
core.autocrlf
Se você estiver programando no Windows e trabalhando com pessoas que não estão (ou vice-versa), provavelmente enfrentará problemas de terminação de linha em algum momento. Isso ocorre porque o Windows usa um caractere de retorno de carro e um caractere de alimentação de linha para novas linhas em seus arquivos, enquanto os sistemas macOS e Linux usam apenas o caractere de alimentação de linha. Este é um fato sutil, mas incrivelmente irritante do trabalho multiplataforma; muitos editores no Windows substituem silenciosamente as terminações de linha estilo LF existentes por CRLF, ou inserem ambos os caracteres de terminação de linha quando o usuário pressiona a tecla Enter.
O Git pode lidar com isso convertendo automaticamente as terminações de linha CRLF em LF quando você adiciona um arquivo ao índice, e vice-versa quando ele faz o checkout do código no seu sistema de arquivos.
Você pode ativar essa funcionalidade com a configuração core.autocrlf.
Se você estiver em uma máquina Windows, defina-a como true — isso converte as terminações LF em CRLF quando você faz o checkout do código:
$ git config --global core.autocrlf true
Se você estiver em um sistema Linux ou macOS que usa terminações de linha LF, você não vai querer que o Git as converta automaticamente quando você fizer o checkout de arquivos; no entanto, se um arquivo com terminações CRLF for introduzido acidentalmente, você pode querer que o Git o conserte.
Você pode dizer ao Git para converter CRLF em LF no commit, mas não o contrário, configurando core.autocrlf como input:
$ git config --global core.autocrlf input
Essa configuração deve deixá-lo com terminações CRLF nos checkouts do Windows, mas terminações LF nos sistemas macOS e Linux e no repositório.
Se você for um programador Windows fazendo um projeto exclusivo para Windows, poderá desativar essa funcionalidade, registrando os retornos de carro no repositório, configurando o valor da configuração para false:
$ git config --global core.autocrlf false
core.whitespace
O Git vem pré-configurado para detectar e corrigir alguns problemas de espaço em branco. Ele pode procurar seis problemas principais de espaço em branco — três estão habilitados por padrão e podem ser desativados, e três estão desabilitados por padrão, mas podem ser ativados.
Os três que estão ativados por padrão são blank-at-eol, que procura espaços no final de uma linha; blank-at-eof, que detecta linhas em branco no final de um arquivo; e space-before-tab, que procura espaços antes de tabulações no início de uma linha.
Os três que estão desativados por padrão, mas podem ser ativados, são indent-with-non-tab, que procura linhas iniciadas por espaços em vez de tabulações (e é controlado pela opção tabwidth); tab-in-indent, que procura tabulações na parte de indentação de uma linha; e cr-at-eol, que informa ao Git que retornos de carro no final das linhas são aceitáveis.
Você pode dizer ao Git quais deles você deseja habilitar configurando core.whitespace para os valores que deseja ativar ou desativar, separados por vírgulas.
Você pode desativar uma opção adicionando um - na frente do seu nome, ou usar o valor padrão, deixando-o fora da string de configuração por completo.
Por exemplo, se você quiser que todos, exceto o space-before-tab, sejam definidos, você pode fazer isso (sendo trailing-space um atalho para cobrir tanto o blank-at-eol quanto o blank-at-eof):
$ git config --global core.whitespace \
trailing-space,-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol
Ou você pode especificar apenas a parte de customização:
$ git config --global core.whitespace \
-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol
O Git detectará esses problemas quando você executar um comando git diff e tentará colori-los para que você possa corrigi-los antes de fazer o commit.
Ele também usará esses valores para ajudá-lo quando você aplicar patches com git apply.
Quando estiver aplicando patches, você pode pedir ao Git para avisá-lo se ele estiver aplicando patches com os problemas de espaço em branco especificados:
$ git apply --whitespace=warn <patch>
Ou você pode fazer com que o Git tente corrigir o problema automaticamente antes de aplicar o patch:
$ git apply --whitespace=fix <patch>
Essas opções se aplicam ao comando git rebase também.
Se você fez commit de problemas de espaço em branco, mas ainda não fez push para o upstream, pode executar git rebase --whitespace=fix para que o Git corrija automaticamente os problemas de espaço em branco enquanto reescreve os patches.
Configuração de Servidor
Não há tantas opções de configuração disponíveis para o lado do servidor do Git, mas há algumas interessantes das quais você pode querer tomar nota.
receive.fsckObjects
O Git é capaz de se certificar de que todo objeto recebido durante um push ainda corresponde ao seu checksum SHA-1 e aponta para objetos válidos.
No entanto, ele não faz isso por padrão; é uma operação bastante custosa, e pode tornar a operação mais lenta, especialmente em repositórios ou pushes grandes.
Se você quiser que o Git verifique a consistência do objeto em cada push, você pode forçá-lo a fazê-lo definindo receive.fsckObjects como verdadeiro:
$ git config --system receive.fsckObjects true
Agora, o Git verificará a integridade do seu repositório antes de cada push ser aceito, a fim de garantir que clientes defeituosos (ou maliciosos) não estejam introduzindo dados corrompidos.
receive.denyNonFastForwards
Se você fizer rebase de commits que já enviou e tentar fazer push novamente, ou tentar enviar para uma branch remota um commit que não contenha aquele para o qual a branch remota aponta atualmente, o envio será negado.
Geralmente, essa é uma boa política; mas, no caso do rebase, você pode chegar à conclusão de que sabe o que está fazendo e forçar a atualização da branch remota utilizando a flag -f no seu comando de push.
Para dizer ao Git que recuse os pushes forçados, configure o receive.denyNonFastForwards:
$ git config --system receive.denyNonFastForwards true
A outra maneira de fazer isso é por meio de hooks de recebimento no lado do servidor, que abordaremos em breve. Essa abordagem permite que você faça coisas mais complexas, como negar os não-fast-forwards para um determinado subconjunto de usuários.
receive.denyDeletes
Uma forma de contornar a política denyNonFastForwards é o usuário excluir a branch e depois enviá-la novamente com a nova referência.
Para evitar isso, defina receive.denyDeletes como true:
$ git config --system receive.denyDeletes true
Isto nega qualquer deleção de branches ou tags — nenhum usuário poderá fazê-lo. Para remover branches remotas, você precisa excluir manualmente os arquivos de referência no servidor. Também há maneiras mais interessantes de fazer isso por usuário, por meio de ACLs, como você aprenderá em Uma Política de Exemplo Imposta pelo Git.