Acrescenta um índice com outras páginas.
[cursogit.git] / Colaborando_com_Git.mdwn
index cb498cd..373ff00 100644 (file)
@@ -99,4 +99,206 @@ renomear, o subcomando rename.
 
 ## Fazendo atualizações
 
+Após adicionar um remoto, queremos fazer o download dos branches e
+commits remotos. Um dos comandos que pode ser utilizado é git fetch.
+
+       ~/project$ git fetch alice
+       From git://alice.example.com/project.git/
+        * [new branch]      master     -> alice/master
+        * [new branch]      shell      -> alice/shell
+       ~/project$ git branch -r
+         alice/master
+         alice/shell
+         origin/HEAD -> origin/master
+         origin/devel
+         origin/master
+       ~/project$ 
+
+Note que ao realizar o fetch, diferente do clone, não é criada uma
+referência ao HEAD do repositório remoto. Tampouco, é criado um branch
+local, ou feito um checkout. As referências, no entanto, são escritas
+localmente, de tal forma que é possível investigar os commits dos
+branches remotos sem novo acesso à rede.
+
+Como o acesso à rede não é feito a cada comando, novas atualizações
+precisam ser feitas quando o repositório remoto é atualizado e deseja-se
+investigar novos branches ou novos commits. Além de git fetch, pode ser
+utilizado git remote update.
+
+       ~/project$ git remote update
+       Fetching origin
+       Fetching alice
+       From git://alice.example.com/project.git/
+        * [new branch]      devel      -> alice/devel
+       ~/project$ 
+
+Veja que um novo branch foi atualizado.
+
+## Branches remotos
+
+Agora que temos uma lista de branches remotos, podemos manipulá-los como
+branches locais, usando git log, git diff, entre outros comandos.
+Podemos fazer um checkout de um branch remoto, criando um branch local.
+
+       ~/project$ git checkout -b shell alice/shell
+       Branch shell set up to track remote branch shell from alice.
+       Switched to a new branch 'shell'
+       ~/project$ git branch -vv
+         master 033d4b8 [origin/master] Acrescenta lista de arquivos a serem ignorados.
+       * shell  a5cb5bb [alice/shell] Implementação de hello em shell script.
+       ~/project$ 
+
+A opção -vv de git branch mostra o commit ID, o sumário do commit, e o
+branch remoto que é rastreado pelo branch local. O rastreamento de um
+branch local é importante para comandos como git push e git pull, que
+veremos logo mais.
+
+## Atualizando repositórios remotos
+
+Após clonar ou adicionar um repositório remoto com uma URL que permite
+escrita, poderemos atualizá-lo através do comando git push.
+
+O comportamento de git push sofreu alterações ao longo das versões de
+Git. Veremos alguns destes comportamentos padrões, e como utilizar
+parâmetros explícitos para evitar surpresas.
+
+       ~/project$ git add hello.c
+       ~/project$ git commit -m "Utiliza world sem capitalização"
+       [master 18c7b69] Utiliza world sem capitalização
+        1 file changed, 1 insertion(+), 1 deletion(-)
+       ~/project$ git push origin master:master
+       Counting objects: 3, done.
+       Delta compression using up to 4 threads.
+       Compressing objects: 100% (3/3), done.
+       Writing objects: 100% (3/3), 321 bytes | 0 bytes/s, done.
+       Total 3 (delta 2), reused 0 (delta 0)
+       To /home/user2/project
+          033d4b8..18c7b69  master -> master
+       ~/project$ 
+
+Adicionamos um novo commit ao nosso histórico, e fazemos uma atualização
+no repositório remoto origin. O primeiro parâmetro é o repositório
+remoto que queremos atualizar. O segundo parâmetro, chamado refspec,
+especifica o branch local e o branch remoto que serão sincronizados.
+
+No exemplo acima, o branch local master foi utilizado para atualizar o
+branch remoto master. Objetos são escritos no repositório remoto, e a
+referência atualizada.
+
+Note que o branch de origem deve conter todos os commits no branch de
+destino a ser atualizado. Caso contrário, o push não avançará o branch
+remoto, o que chamamos de fast-forward. Veremos mais à frente as
+condições para termos uma situação de fast-forward.
+
+Tanto o remoto quanto o refspec podem ser omitidos. O padrão em versões
+anteriores à versão 2.0.0 do Git era fazer o push de todos os branches
+com nomes iguais ao repositório remoto especificado explicitamente ou
+implicitamente. Se o remoto não é especificado, é assumido o remoto que
+o branch corrente rastreia.
+
+No exemplo sobre Branches remotos acima, o branch local shell rastreia o
+branch remoto alice/shell. Caso este branch seja o branch corrente, git
+push utilizaria por padrão o repositório remoto alice. O refspec
+matching, como é chamado o padrão utilizado em versões anteriores à Git
+2.0.0, atualizaria todos os branches no remoto alice que tivessem um
+branch local com o mesmo nome. Ou seja, se alice tivesse branches
+master, devel e shell, e estes mesmos branches existissem localmente,
+todos seriam atualizados. Ainda que o branch local master rastreasse o
+branch remoto origin/master, alice/master seria atualizado neste caso
+específico. Se o branch corrente fosse master, que rastreasse
+origin/master, o repositório remoto origin seria atualizado no lugar do
+repositório remoto alice.
+
+O novo padrão, a partir da versão 2.0.0, se chama simple. Ele atualiza
+apenas o branch atual, apenas se o branch remoto rastreado tiver o mesmo
+nome.
+
+As outras opções, sendo todas elas configuráveis globalmente ou por
+repositório, através da opção push.default, são upstream, current e
+nothing. A opção nothing exige que o refspec esteja explícito na linha
+de comando. A opção current atualiza no remoto especificado ou ímplicito
+o branch com o mesmo nome que o branch local corrente. E a opção
+upstream atualiza o branch remoto rastreado pelo branch corrente.
+
+## Repositórios bare
+
+É importante mencionar que ao realizar push em um repositório com um
+diretório de trabalho, o diretório de trabalho e o índice não são
+atualizados, mesmo que o branch corrente seja o branch atualizado. Isto
+pode causar problemas, caso o diretório de trabalho seja atualizado.
+Portanto, o padrão em versões desde 1.7.0 é impedir que tal branch seja
+atualizado, a não ser que a opção de configuração
+receive.denyCurrentBranch utilize os valores warn, false ou ignore.
+
+Anteriormente à versão 1.7.0, o diretório de trabalho era atualizado
+quando um push era feito. Isso poderia ser perigoso, pois o diretório de
+trabalho poderia conter alterações que não foram gravadas, causando a
+perda de dados.
+
+Mas existe um tipo de repositório que não possui diretório de trabalho,
+e pode evitar problemas como esses. Este tipo de repositório é conhecido
+como repositório bare. Ele pode ser criado com a opção --bare de git
+init ou de git clone. Geralmente, por convenção, tais repositórios têm a
+URL terminada em .git.
+
+       $ git clone --bare project/ project.git/
+       Cloning into bare repository 'project.git'...
+       done.
+       $
+
 ## Publicando um repositório
+
+Vimos como trabalhar com um repositório remoto, obtendo seus commits
+para trablharmos localmente. No entanto, o caminho reverso é necessário
+para publicarmos os commits locais para que outros possam trabalhar com
+eles.
+
+Há várias formas de fazê-lo. Veremos aqui algumas delas, utilizando um
+host próprio, que seja acessível ao público alvo, através de SSH, HTTP
+ou git daemon.
+
+### SSH
+
+Publicar através de SSH é simples de ser feito, mas tem algumas
+implicações. Entre elas é o acesso exigido a um shell no host para os
+usuários, dificultando acesso anônimo e criando um novo problema de
+segurança a ser resolvido. A outra implicação é que o acesso por
+múltiplos usuários a um mesmo repositório exige um cuidado especial para
+evitar problemas de permissão quando um usuário publica novos commits e
+outros objetos. Há algumas soluções que resolvem alguns desses
+problemas, criando um shell e um usuário especial para uso dedicado a
+repositórios Git. Veremos, no entanto, apenas a solução mais comum, que
+não exige outro software instalado no host, além de Git.
+
+Uma excelente forma de utilizar a publicação via SSH é disponibilizá-la
+de forma somente leitura através de outros métodos, e ter um único
+usuário que possa atualizá-lo, o que resolve vários dos problemas já
+mencionados.
+
+Há duas formas simples para publicar um repositório via SSH. Uma delas é
+criar um bare clone do repositório e fazer a cópia para o host remoto,
+através do método de preferência. Uma opção é scp.
+
+       $ git clone --bare project/
+       Cloning into bare repository 'project.git'...
+       done.
+       $ scp -rq project.git/ git.example.com:/srv/git/alice/
+       $ 
+
+A outra opção é criar um repositório bare no host remoto, e fazer o
+primeiro push.
+
+       alice@git.example.com $ mkdir project.git
+       alice@git.example.com $ cd project.git
+       alice@git.example.com project.git$ git init --bare
+       Initialized empty Git repository in /srv/git/alice/project.git/
+       alice@git.example.com project.git$ 
+       
+       ~/project$ git remote add origin git.example.com:/srv/git/alice/project.git/
+       ~/project$ git push origin master:master
+       Counting objects: 3, done.
+       Writing objects: 100% (3/3), 229 bytes, done.
+       Total 3 (delta 0), reused 0 (delta 0)
+       To git.example.com:/srv/git/alice/project.git/
+        * [new branch]      master -> master
+       ~/project$