Merge git://github.com/damianmichna/gitmagic
[gitmagic.git] / pt_br / secrets.txt
blob2f2e8f2fffaccc56ad78ae25b40808350e192ddd
1 == Segredos Revelados ==
3 Vamos dar uma espiada sob o capô e explicar como o Git realiza seus milagres. Será uma explicação superficial. Para detalhes mais aprofundados consultar o http://schacon.github.com/git/user-manual.html[manual do usuário].
5 === Invisibilidade ===
7 Como pode o Git ser tão discreto? Fora ocasionais commit e merge, você pode trabalhar como se desconhecesse que existe um controle de versões. Isto é, até que precise dele, e é quando você ficará agradecido ao Git por estar vigiando o que faz o tempo todo.
9 Outros sistemas de controle de versões não deixam você esquecê-los. As permissões dos arquivos são apenas de leitura, a menos que você diga ao servidor quais arquivos tem a intenção de editar. Os comandos mais básicos podem demorar muito quando o número de usuários aumenta. O trabalho pode ser interrompido quando a rede ou o servidor central para.
11 Ao contrário, o Git guarda o histórico do seu projeto no diretório `.git` no diretório de trabalho. Essa é a sua cópia do histórico, de modo que você pode ficar offline até que deseje se comunicar com os outros. Você tem total controle sobre o destino de seus arquivos, pois o Git pode facilmente recriar um estado salvo a partir do `.git` a qualquer hora.
13 === Integridade ===
15 A maioria das pessoas associam criptografia com manter informações secretas, mas outra aplicação igualmente importante é manter a integridade da informação. O uso correto das funções criptográficas de hash pode prevenir o corrupção acidental ou intencional dos dados.
17 Um hash SHA1 pode ser entendido como um número identificador único de 160 bits para cada sequência de bytes que você vai encontrar na vida. Na verdade mais que isso: para cada sequência de bytes que qualquer ser humano jamais usará durante várias vidas.
19 Como um hash SHA1 é, ele mesmo, uma sequência de bytes, podemos gerar um hash de sequências de bytes formada por outros hash. Essa observação simples é surpreendentemente útil: a procura por 'cadeias hash'  ('hash chains'). Vamos ver mais adiante como o Git a utiliza para garantir com eficiência a integridade de dados.
21 A grosso modo, o Git mantém os seus arquivos no subdiretório `.git/objects`, onde ao invés de ter arquivos com nomes “normais”, vamos encontrar somente identificadores (Ids). Utilizando os Ids como nomes de arquivos, bem como uns poucos lockfiles e alguns truques com o timestamp, o Git transforma qualquer sistema de arquivos simples em um poderoso banco de dados.
23 === Inteligência ===
25 Como o Git sabe que um arquivo foi renomeado, mesmo que você nunca tenha mencionado o fato explicitamente? Com certeza, você executou *git mv*, mas isto é exatamente o mesmo que um *git rm* seguido por um *git add*.
27 A análise heurística do Git verifica além das ações de renomear e de cópias sucessivas entre versões. De fato, ele pode detectar até pedaços de código sendo movidos ou copiados entre arquivos! Embora não cubra todos os casos, faz um trabalho decente, e esta característica está sendo sempre aprimorada. Caso não funcione com você, tente habilitar opções mais refinadas para detecção de cópias e considere uma atualização.
29 === Indexando ===
31 Para cada arquivo monitorado, o Git armazena informações como: tamanho, hora de criação e última modificação, em um arquivo conhecido como 'index'. Para determinar se um arquivo foi modificado, o Git compara seus status atual com o que tem no index. Se coincidem, então ele pode ignorar o arquivo.
33 Já que verificações de status são imensamente mais baratas que ler o conteúdo do arquivo, se você editar poucos arquivos, o Git vai atualizar seus status quase que instantaneamente.
35 Falamos anteriormente que o index é uma área de atuação (staging). Por que um monte de status de arquivos é uma area de atuação (staging)? É porque o comando add coloca os arquivos no banco de dados do Git e atualiza esse status, enquanto o comando commit, sem opções, cria um commit baseado somente no status e arquivos já existentes no banco de dados.
37 === Origem do Git ===
39 Esta http://lkml.org/lkml/2005/4/6/121[mensagem na lista de discussão do Linux Kernel] descreve a sequência de eventos que levaram ao Git. A discussão inteira é um sitio arqueológico fascinante para historiadores do Git.
41 === O Banco de Dados de Objetos ===
43 Cada versão de seus dados é mantida em um 'bando de dados de objetos', que reside no subdiretório `.git/objects`: os outros residentes de `.git/` armazenam menos dados: o index, nomes dos branchs, etiquetas (tags), configurações de opções, logs, a localização do commit HEAD, e outros. O bando de dados objeto é elementar e elegante, e a origem do poder do Git.
45 Cada arquivo dentro de `.git/objects` é um 'objeto'. Existem 3 tipos de objetos que nos interessam: objetos 'blob', objetos 'árvores' ('tree'), e objetos 'commit'.
47 === Blobs ===
49 Primeiro, um truque mágico. Peque um nome de arquivo, qualquer arquivo. Em um diretório vazio, execute
51  $ echo sweet > YOUR_FILENAME
52  $ git init
53  $ git add .
54  $ find .git/objects -type f
56 Voce verá +.git/objects/aa/823728ea7d592acc69b36875a482cdf3fd5c8d+.
58 Como eu posso saber disso, sem saber o nome do arquivo? É por que o hash SHA1 de:
60  "blob" SP "6" NUL "sweet" LF
62 é aa823728ea7d592acc69b36875a482cdf3fd5c8d,
63 onde SP é espaço, NUL é o byte zero e LF é um linefeed. Você pode verificar isso, digitando:
65   $ printf "blob 6\000sweet\n" | sha1sum
67 O Git é 'endereçável-por-conteúdo': os arquivos não são armazenados de acordo com seus nomes de arquivos, e sim pelo hash de seus dados, em um arquivo que chamamos de 'objeto blob' ('blob object'). Podemos pensar que o hash é um identificador único para o conteúdo do arquivo, de modo que estamos endereçando os arquivos pelo seu conteúdo. O `blob 6` inicial é meramente um header que consiste do tipo do objeto e seu tamanho em bytes; isso simplifica a organização interna.
69 Assim eu poderia prever o que você irá ver. O nome do arquivo é irrelevante: somente os dados internos são utilizados para construir o objeto blob.
71 Você pode estar se perguntando o que acontece com os arquivos idênticos. Tente adicionar cópias de seu arquivo, com qualquer nome de arquivo. O conteúdo do +.git/objects+ continua o mesmo não importa quantos você adiciona. O Git somente armazena o dado uma única vez.
73 A propósito, os arquivos dentro de +.git/objects+ são comprimidos com a zlib de modo que você não consegue examiná-los diretamente. Faça uma filtragem por meio do http://www.zlib.net/zpipe.c[zpipe -d], ou digite:
75  $ git cat-file -p aa823728ea7d592acc69b36875a482cdf3fd5c8d
77 que mostra o objeto em um formato legível.
79 === Árvores ===
81 Mas onde estão os nomes de arquivos? Eles precisam ser armazenados em algum lugar. Git fica sabendo o nome do arquivo durante um commit:
83  $ git commit  # Type some message.
84  $ find .git/objects -type f
86 Você pode ver agora 3 objetos. Dessa vez eu não consigo dizer quais os dois nomes de arquivos, já que eles dependem parcialmente do nome do arquivo que você escolheu. Vamos prosseguir assumindo que você escolheu ``rose''. Se não escolheu esse nome, você pode reescrever o histórico para ficar parecido com o que você fez:
88  $ git filter-branch --tree-filter 'mv YOUR_FILENAME rose'
89  $ find .git/objects -type f
91 Agora você poderá ver o arquivo
92 +.git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9+, porque esse é o hash SHA 1 de seu conteudo:
94  "tree" SP "32" NUL "100644 rose" NUL 0xaa823728ea7d592acc69b36875a482cdf3fd5c8d
96 Verifique que este arquivo contém efetivamente o que falamos acima, digitando:
98  $ echo 05b217bb859794d08bb9e4f7f04cbda4b207fbe9 | git cat-file --batch
100 Com o zpipe, é fácil verificar o hash:
102  $ zpipe -d < .git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9 | sha1sum
104 A verificação do hash é mais complicada via cat-file porque sua saida contem mais do que os dados descomprimidos do arquivo object.
106 Esse arquivo é um objeto 'árvore' ('tree'): uma lista de tuplas que consiste em um tipo de arquivo, um nome de arquivo e um hash. Em nosso exemplo, este tipo de arquivo é 100644, que significa que `rose` é um arquivo normal, e o hash é o objeto blob que  contém o termo `rose'. Outros tipos possíveis de arquivos são executáveis, symlinks e diretorios. No ultimo exemplo, o hash aponta para um objeto árvore.
108 Se você executar o filter-branch, você obterá objetos antigos que não precisa mais. Embora sejam eliminados automaticamente quando o período de armazenamento expirar, iremos deletá-los agora para tornar o nosso exemplo mais fácil de seguir:
110  $ rm -r .git/refs/original
111  $ git reflog expire --expire=now --all
112  $ git prune
114 Para projetos reais você deve tipicamente evitar comandos como esses, já que eles destroem os backups. Se você deseja um repositório limpo, é geralmente melhor criar um novo clone. Também, tome cuidado quando manipular diretamente o +.git+: e se um comando Git esta executando ao mesmo tempo, ou uma falha na alimentação eletrica ocorre? Geralmente, as referências podem ser deletadas com *git update-ref -d*, embora seja mais seguro remover manualmente o +refs/original+.
116 === Commits ===
118 Explicamos 2 dos 3 objetos. O terceiro é o objeto 'commit'. Seu conteúdo depende da mensagem de commit bem como da data e hora em que foi criado. Para combinar com o que temos aqui, vamos ter que fazer um pequeno truque:
120  $ git commit --amend -m Shakespeare  # Change the commit message.
121  $ git filter-branch --env-filter 'export
122      GIT_AUTHOR_DATE="Fri 13 Feb 2009 15:31:30 -0800"
123      GIT_AUTHOR_NAME="Alice"
124      GIT_AUTHOR_EMAIL="alice@example.com"
125      GIT_COMMITTER_DATE="Fri, 13 Feb 2009 15:31:30 -0800"
126      GIT_COMMITTER_NAME="Bob"
127      GIT_COMMITTER_EMAIL="bob@example.com"'  # Rig timestamps and authors.
128  $ find .git/objects -type f
130 Agora você pode ver
131 +.git/objects/49/993fe130c4b3bf24857a15d7969c396b7bc187+
132 que é o hash SHA 1 de seu conteúdo:
134  "commit 158" NUL
135  "tree 05b217bb859794d08bb9e4f7f04cbda4b207fbe9" LF
136  "author Alice <alice@example.com> 1234567890 -0800" LF
137  "committer Bob <bob@example.com> 1234567890 -0800" LF
138  LF
139  "Shakespeare" LF
141 Como anteriormente, você pode executar o zpipe ou cat-file para ver você mesmo.
143 Esse é o primeiro commit, de modo que não existe nenhum commit pai, mas commit posteriores irão sempre conter no mínimo uma linha identificando o seu commit pai.
145 === Indistinguível da Magia ===
147 O segredo do Git parece ser tão simples. Parece que você pode misturar um pouco de script shell e adicionar uma pitada de código C para cozinha-lo em questão de horas: uma mistura de operações básicas do sistema de arquivos e hash SHA 1, guarnecido com arquivos lock e fsyncs para robustez. De fato, isso descreve acuradamente as primeiras versões do Git. No entanto, além de truques engenhosos de empacotamento para economizar espaço, e truques engenhosos de indexação para economizar espaço, agora sabemos como o Git habilmente transforma um sistema de arquivos em um banco de dados perfeito para o controle de versões.
149 Por exemplo, se algum arquivo dentro do banco de dados de objetos é corrompido por um erro de disco, então o seu hash não irá corresponder mais, alertando-nos sobre o problema. Fazendo hash de hash de outros objetos, mantemos a integridade em todos os níveis. Os commits são atomicos, isto é, um commit nunca pode armazenar parcialmente as mudanças: só podemos calcular o hash de um commit e armazenar ele no banco de dados após ter armazenado todas as árvores relevantes, blobs e os commits pais. O banco de dados de objetos é imune a interrupções inesperadas tais como falha de alimentação eletrica.
151 Nós derrotamos até mesmo os adversários mais tortuosos. Suponha que alguem tente  de maneira escondida, modificar o conteudo de um arquivo em uma versão antiga do projeto. Para manter o banco de dados dos objetos com uma aparência saudável, ele deve também alterar o hash do objeto blob correspondente, já que ele contem agora uma cadeia de bytes diferente. Isso significa que ele terá que alterar o hash de qualquer objeto árvore que referencia o arquivo, e em seguida alterar o hash de todos os objetos commit que estão envolvidos com esses objetos árvores, além dos hash de todos os descendentes desses commits. Isso significa que o hash do Head oficial será diferente do hash do repositório alterado. Seguindo a trilha dos hash não correspondentes podemos apontar o arquivo alterado, bem como o commit onde ele foi corrompido.
153 Resumindo, graças aos 20 bytes que representam o ultimo commit seguro, é impossível adulterar um repositório Git.
155 É sobre as famosas características do Git? Branching, Merging? Tags? Meros detalhes. O cabeçalho atual é mantido em um arquivo +.git/HEAD+, que contém um hash de um objeto commit. O hash é atualizado durante um commit bem como com muitos outros comandos. Branch são quase a mesma coisa: eles são arquivos em +.git/refs/heads+. Tags também: elas estão em +.git/refs/tags+ mas são atualizadas por um conjunto diferente de comandos.