Repositório bare.
[cursogit.git] / Colaborando_com_Git.mdwn
1 # Colaborando com Git
2
3 Git funciona localmente. Commits, branches, logs estão gravados no
4 repositório local. Para colaborar com outros projetos, precisamos
5 publicar e ter acesso a repositórios públicos.
6
7 É possível publicar através de vários protocolos. Além de um diretório
8 local, uma das formas mais simples é utilizar SSH, já que independe de
9 outra configuração e permite escrita. HTTP é uma boa opção somente
10 leitura para repositórios públicos, já que não exige credenciais para
11 acesso. A outra opção é o protocolo próprio do Git, através do git
12 daemon.
13
14 ## Clonando Repositórios
15
16 Para criar um novo repositório a partir de um repositório publicado,
17 usamos o comando git clone.
18
19         ~/$ git clone /home/user2/project
20         Cloning into 'project'...
21         done.
22         ~/$ cd project
23         ~/project$ ls -a
24         .  ..  .git  README
25         ~/project$ 
26
27 Quando um repositório é clonado, temos uma cópia local das referências
28 deste repositório. O repositório é registrado com um nome, sendo origin
29 o nome padrão, e as referências a seus branches são prefixadas com este
30 nome e uma barra. Para visualizar estes branches remotos, utilizamos a
31 opção -r do comando git branch.
32
33         ~/project$ git branch -r
34           origin/HEAD -> origin/master
35           origin/master
36         ~/project$ 
37
38 Note que o HEAD do repositório remoto aponta para o branch remoto
39 chamado master. O HEAD remoto é utilizado para criar um novo branch
40 local quando o repositório é clonado.
41
42         ~/project$ git branch
43         * master
44         ~/project$ 
45
46 ## Remotes
47
48 Com Git, é possível colaborar com mais de um repositório remoto. A lista
49 de repositórios rastreados, com seus nomes e URLs fica no arquivo de
50 configuração do repositório, ou seja, $REPODIR/.git/config.
51
52 Para manipular esta lista, o comando git remote pode ser útil. É
53 possível listar, adicionar, remover, renomear repositórios remotos.
54
55 Ao clonar um repositório, o remoto origin já é criado. Este é o nome
56 padrão para comandos que aceitam um remoto como parâmetro, mas permitem
57 que seja omitido, assumindo o remoto origin.
58
59         ~/project$ git remote
60         origin
61         ~/project$ 
62
63 Para adicionar um novo remoto, usamos o subcomando add, passando um nome
64 e uma URL como parâmetros.
65
66         ~/project$ git remote add git://alice.example.com/project.git/
67         ~/project$ git remote show
68         alice
69         origin
70         ~/project$ git remote show -n alice
71         * remote alice
72           Fetch URL: git://alice.example.com/project.git/
73           Push  URL: git://alice.example.com/project.git/
74           HEAD branch: (not queried)
75           Local ref configured for 'git push' (status not queried):
76             (matching) pushes to (matching)
77         ~/project$ 
78
79 Ao adicionar um novo repositório remoto, apenas acrescentamos este
80 repositório ao nosso arquivo de configuração. Não fazemos nenhum
81 download dos seus branches e commits remotos. A opção -n do subcomando
82 show evita buscar dados remotamente, que utilizaria a rede.
83
84 Note que temos duas URLs, uma para fetch e outra para push, que veremos
85 logo a seguir o que significam. Também temos o branch para qual o HEAD
86 do remoto aponta. Neste caso, como o repositório não foi acessado, não
87 temos esta informação. E a configuração para o push, que veremos logo a
88 seguir, fará atualização de branches que se casem.
89
90 Para remover um repositório remoto, utilizamos o subcomando rm, e pare
91 renomear, o subcomando rename.
92
93         ~/project$ git remote rename alice aliceS
94         ~/project$ git remote show
95         aliceS
96         origin
97         ~/project$ git remote rm aliceS
98         ~/project$ 
99
100 ## Fazendo atualizações
101
102 Após adicionar um remoto, queremos fazer o download dos branches e
103 commits remotos. Um dos comandos que pode ser utilizado é git fetch.
104
105         ~/project$ git fetch alice
106         From git://alice.example.com/project.git/
107          * [new branch]      master     -> alice/master
108          * [new branch]      shell      -> alice/shell
109         ~/project$ git branch -r
110           alice/master
111           alice/shell
112           origin/HEAD -> origin/master
113           origin/devel
114           origin/master
115         ~/project$ 
116
117 Note que ao realizar o fetch, diferente do clone, não é criada uma
118 referência ao HEAD do repositório remoto. Tampouco, é criado um branch
119 local, ou feito um checkout. As referências, no entanto, são escritas
120 localmente, de tal forma que é possível investigar os commits dos
121 branches remotos sem novo acesso à rede.
122
123 Como o acesso à rede não é feito a cada comando, novas atualizações
124 precisam ser feitas quando o repositório remoto é atualizado e deseja-se
125 investigar novos branches ou novos commits. Além de git fetch, pode ser
126 utilizado git remote update.
127
128         ~/project$ git remote update
129         Fetching origin
130         Fetching alice
131         From git://alice.example.com/project.git/
132          * [new branch]      devel      -> alice/devel
133         ~/project$ 
134
135 Veja que um novo branch foi atualizado.
136
137 ## Branches remotos
138
139 Agora que temos uma lista de branches remotos, podemos manipulá-los como
140 branches locais, usando git log, git diff, entre outros comandos.
141 Podemos fazer um checkout de um branch remoto, criando um branch local.
142
143         ~/project$ git checkout -b shell alice/shell
144         Branch shell set up to track remote branch shell from alice.
145         Switched to a new branch 'shell'
146         ~/project$ git branch -vv
147           master 033d4b8 [origin/master] Acrescenta lista de arquivos a serem ignorados.
148         * shell  a5cb5bb [alice/shell] Implementação de hello em shell script.
149         ~/project$ 
150
151 A opção -vv de git branch mostra o commit ID, o sumário do commit, e o
152 branch remoto que é rastreado pelo branch local. O rastreamento de um
153 branch local é importante para comandos como git push e git pull, que
154 veremos logo mais.
155
156 ## Atualizando repositórios remotos
157
158 Após clonar ou adicionar um repositório remoto com uma URL que permite
159 escrita, poderemos atualizá-lo através do comando git push.
160
161 O comportamento de git push sofreu alterações ao longo das versões de
162 Git. Veremos alguns destes comportamentos padrões, e como utilizar
163 parâmetros explícitos para evitar surpresas.
164
165         ~/project$ git add hello.c
166         ~/project$ git commit -m "Utiliza world sem capitalização"
167         [master 18c7b69] Utiliza world sem capitalização
168          1 file changed, 1 insertion(+), 1 deletion(-)
169         ~/project$ git push origin master:master
170         Counting objects: 3, done.
171         Delta compression using up to 4 threads.
172         Compressing objects: 100% (3/3), done.
173         Writing objects: 100% (3/3), 321 bytes | 0 bytes/s, done.
174         Total 3 (delta 2), reused 0 (delta 0)
175         To /home/user2/project
176            033d4b8..18c7b69  master -> master
177         ~/project$ 
178
179 Adicionamos um novo commit ao nosso histórico, e fazemos uma atualização
180 no repositório remoto origin. O primeiro parâmetro é o repositório
181 remoto que queremos atualizar. O segundo parâmetro, chamado refspec,
182 especifica o branch local e o branch remoto que serão sincronizados.
183
184 No exemplo acima, o branch local master foi utilizado para atualizar o
185 branch remoto master. Objetos são escritos no repositório remoto, e a
186 referência atualizada.
187
188 Note que o branch de origem deve conter todos os commits no branch de
189 destino a ser atualizado. Caso contrário, o push não avançará o branch
190 remoto, o que chamamos de fast-forward. Veremos mais à frente as
191 condições para termos uma situação de fast-forward.
192
193 Tanto o remoto quanto o refspec podem ser omitidos. O padrão em versões
194 anteriores à versão 2.0.0 do Git era fazer o push de todos os branches
195 com nomes iguais ao repositório remoto especificado explicitamente ou
196 implicitamente. Se o remoto não é especificado, é assumido o remoto que
197 o branch corrente rastreia.
198
199 No exemplo sobre Branches remotos acima, o branch local shell rastreia o
200 branch remoto alice/shell. Caso este branch seja o branch corrente, git
201 push utilizaria por padrão o repositório remoto alice. O refspec
202 matching, como é chamado o padrão utilizado em versões anteriores à Git
203 2.0.0, atualizaria todos os branches no remoto alice que tivessem um
204 branch local com o mesmo nome. Ou seja, se alice tivesse branches
205 master, devel e shell, e estes mesmos branches existissem localmente,
206 todos seriam atualizados. Ainda que o branch local master rastreasse o
207 branch remoto origin/master, alice/master seria atualizado neste caso
208 específico. Se o branch corrente fosse master, que rastreasse
209 origin/master, o repositório remoto origin seria atualizado no lugar do
210 repositório remoto alice.
211
212 O novo padrão, a partir da versão 2.0.0, se chama simple. Ele atualiza
213 apenas o branch atual, apenas se o branch remoto rastreado tiver o mesmo
214 nome.
215
216 As outras opções, sendo todas elas configuráveis globalmente ou por
217 repositório, através da opção push.default, são upstream, current e
218 nothing. A opção nothing exige que o refspec esteja explícito na linha
219 de comando. A opção current atualiza no remoto especificado ou ímplicito
220 o branch com o mesmo nome que o branch local corrente. E a opção
221 upstream atualiza o branch remoto rastreado pelo branch corrente.
222
223 ## Repositórios bare
224
225 É importante mencionar que ao realizar push em um repositório com um
226 diretório de trabalho, o diretório de trabalho e o índice não são
227 atualizados, mesmo que o branch corrente seja o branch atualizado. Isto
228 pode causar problemas, caso o diretório de trabalho seja atualizado.
229 Portanto, o padrão em versões desde 1.7.0 é impedir que tal branch seja
230 atualizado, a não ser que a opção de configuração
231 receive.denyCurrentBranch utilize os valores warn, false ou ignore.
232
233 Mas existe um tipo de repositório que não possui diretório de trabalho,
234 e pode evitar problemas como esse. Este tipo de repositório é conhecido
235 como repositório bare. Ele pode ser criado com a opção --bare de git
236 init ou de git clone. Geralmente, por convenção, tais repositórios têm a
237 URL terminada em .git.
238
239         $ git clone --bare project/ project.git/
240         Cloning into bare repository 'project.git'...
241         done.
242         $
243
244 ## Publicando um repositório
245
246 Vimos como trabalhar com um repositório remoto, obtendo seus commits
247 para trablharmos localmente. No entanto, o caminho reverso é necessário
248 para publicarmos os commits locais para que outros possam trabalhar com
249 eles.
250
251 Há várias formas de fazê-lo. Veremos aqui algumas delas, utilizando um
252 host próprio, que seja acessível ao público alvo, através de SSH, HTTP
253 ou git daemon.
254
255 Publicar através de SSH é simples de ser feito, mas tem algumas
256 implicações. Entre elas é o acesso exigido a um shell no host para os
257 usuários, dificultando acesso anônimo e criando um novo problema de
258 segurança a ser resolvido. A outra implicação é que o acesso por
259 múltiplos usuários a um mesmo repositório exige um cuidado especial para
260 evitar problemas de permissão quando um usuário publica novos commits e
261 outros objetos. Há algumas soluções que resolvem alguns desses
262 problemas, criando um shell e um usuário especial para uso dedicado a
263 repositórios Git. Veremos, no entanto, apenas a solução mais comum, que
264 não exige outro software instalado no host, além de Git.
265
266 Uma excelente forma de utilizar a publicação via SSH é disponibilizá-la
267 de forma somente leitura através de outros métodos, e ter um único
268 usuário que possa atualizá-lo, o que resolve vários dos problemas já
269 mencionados.