Como criar um commit fast-forward de dois branches?
[cursogit.git] / Colaborando_com_Git.mdwn
index 0172b2e..373ff00 100644 (file)
@@ -128,7 +128,7 @@ utilizado git remote update.
        ~/project$ git remote update
        Fetching origin
        Fetching alice
        ~/project$ git remote update
        Fetching origin
        Fetching alice
-       From /home/cascardo/git/ff/project
+       From git://alice.example.com/project.git/
         * [new branch]      devel      -> alice/devel
        ~/project$ 
 
         * [new branch]      devel      -> alice/devel
        ~/project$ 
 
@@ -153,6 +153,99 @@ 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.
 
 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
 ## Publicando um repositório
 
 Vimos como trabalhar com um repositório remoto, obtendo seus commits
@@ -164,6 +257,8 @@ 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.
 
 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
 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
@@ -179,3 +274,31 @@ 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.
 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$