Exercício – Colaborar com outras pessoas usando um repositório compartilhado

Concluído

O pull direto do repositório de outra pessoa funciona, desde que você esteja na mesma rede. Mas é um processo complicado, e a maioria dos colaboradores não está na mesma rede. É melhor configurar um repositório central em que todos os colaboradores possam efetuar push e pull.

Quando você conta sobre seu projeto ao seu amigo desenvolvedor Pedro e ele pede para participar, isso é exatamente o que você decide fazer: configurar um repositório central, que também é chamado de repositório simples.

Criar um repositório simples

O que você precisa é de um repositório que não tenha uma árvore de trabalho. Um repositório simples tem várias vantagens em relação a uma árvore de trabalho:

  • Sem uma árvore de trabalho, todos podem efetuar push das alterações sem se preocupar com o check-out do branch.
  • É fácil para o Git detectar quando outro usuário enviou por push as alterações que podem entrar em conflito com as suas.
  • Um repositório compartilhado é dimensionado para qualquer número de desenvolvedores. Com um repositório simples, você precisa saber apenas sobre o repositório compartilhado, não sobre todos os outros colaboradores dos quais você pode precisar efetuar pull.
  • Ao colocar o repositório compartilhado em um servidor que todos vocês podem acessar, você não precisará se preocupar com firewalls e permissões.
  • Você não precisa ter contas separadas no servidor, pois o Git controla quem fez cada commit. (O GitHub tem milhões de usuários, todos compartilhando a conta git. Todos usam o protocolo de rede de criptografia SSH (Secure Shell), e os usuários são diferenciados pelas respectivas chaves públicas.)

É fácil criar um repositório simples para compartilhamento:

  1. Crie um diretório chamado Shared.git no mesmo nível dos diretórios Alice e Cats para manter o repositório simples:

    cd ..
    mkdir Shared.git
    cd Shared.git
    
    

    O nome do diretório não é importante, mas nós nos referiremos a ele como o diretório Shared.git ou apenas o diretório compartilhado nestes exercícios.

    A nomeação do diretório Shared.git segue a longa tradição de atribuição de um nome que termina com .git aos repositórios simples para distingui-los das árvores de trabalho. É uma convenção, mas não um requisito.

  2. Agora, use o seguinte comando para criar um repositório simples no diretório compartilhado:

    git init --bare
    
    
  3. Quando um repositório ainda é simples, o comando git checkout não pode ser usado para definir o nome do branch padrão. Para realizar essa tarefa, você pode alterar o branch HEAD para que ele aponte para outro branch; nesse caso, o branch main:

    git symbolic-ref HEAD refs/heads/main
    
    
  4. A próxima etapa é inserir o conteúdo do seu repositório no repositório compartilhado. Use estes comandos para retornar ao diretório do projeto, em que o repositório está armazenado, configurar um repositório remoto origin e executar um push inicial:

    cd ../Cats
    git remote add origin ../Shared.git
    git push origin main
    
    
  5. Verifique a saída. A saída indicará o sucesso:

    Counting objects: 12, done.
    Delta compression using up to 2 threads.
    Compressing objects: 100% (8/8), done.
    Writing objects: 100% (12/12), 1.07 KiB | 0 bytes/s, done.
    Total 12 (delta 1), reused 0 (delta 0)
    To ../Shared.git
     * [new branch]      main -> main
    
  6. Você deseja que push e pull usem o branch main de origin por padrão, como se você tivesse criado seu repositório clonando-o em primeiro lugar. Para fazer isso, você precisará informar ao Git qual branch ele deverá controlar.

    git branch --set-upstream-to origin/main
    
    
  7. Verifique esta saída:

    Branch main set up to track remote branch main from origin.
    

    O Git indicará um problema se você tentar executar esse comando antes do push inicial, porque o novo repositório não tinha branches. O Git não pode controlar um branch que não existe. Tudo o que o Git faz nos bastidores é procurar em .git/refs/remotes/origin um arquivo chamado trunk.

Configuração para colaboradores

A próxima etapa é que Pedro clonará o repositório simples e que Alice definirá a origem no repositório dela para ser direcionada ao repositório compartilhado para pushes e pulls.

  1. Crie um diretório chamado Pedro que seja irmão do diretório do projeto e altere para o diretório Pedro:

    cd ..
    mkdir Bob
    cd Bob
    
    
  2. Agora, clone o repositório compartilhado (inclua o ponto no final do comando):

    git clone ../Shared.git .
    
    
  3. Atualmente, o repositório de Alice está configurado para efetuar push e pull do repositório dela. Use os seguintes comandos para alterar para o diretório Alice e alterar origin para que ele aponte para o repositório compartilhado:

    cd ../Alice
    git remote set-url origin ../Shared.git
    
    

Começar a colaboração

Agora que Pedro está configurado para trabalhar no site, ele decide adicionar um rodapé à parte inferior da página. Vamos usar a persona de Pedro e Alice por alguns instantes e aprender os conceitos básicos da colaboração.

  1. Comece acessando o diretório Pedro e trabalhando como ele:

    cd ../Bob
    git config user.name Bob
    git config user.email bob@contoso.com
    
    
  2. Abra index.html e substitua o elemento <hr> por esta linha (encontrada no final do elemento <body>):

    <footer><hr>Copyright (c) 2021 Contoso Cats</footer>
    

    Depois, salve o arquivo e feche o editor.

  3. Confirme as alterações e efetue push para a origem remota:

    git commit -a -m "Put a footer at the bottom of the page"
    git push
    
    
  4. Verifique a saída. Se um aviso como o exemplo a seguir for exibido, não se preocupe. Esse aviso só informa os usuários de uma alteração nos comportamentos padrão do Git. Caso deseje ter certeza de que não verá esse aviso novamente, execute git config --global push.default simple.

    warning: push.default is unset; its implicit value has changed in
    Git 2.0 from 'matching' to 'simple'. To squelch this message
    and maintain the traditional behavior, use:
    
      git config --global push.default matching
    
    To squelch this message and adopt the new behavior now, use:
    
      git config --global push.default simple
    
    When push.default is set to 'matching', git will push local branches
    to the remote branches that already exist with the same name.
    
    Since Git 2.0, Git defaults to the more conservative 'simple'
    behavior, which only pushes the current branch to the corresponding
    remote branch that 'git pull' uses to update the current branch.
    
    See 'git help config' and search for 'push.default' for further information.
    (the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
    'current' instead of 'simple' if you sometimes use older versions of Git)
    
  5. Embora Pedro esteja editando o site, Alice também está. Ela decide adicionar uma barra de navegação à página. Essa adição exige que ela modifique dois arquivos: index.html e site.css. Comece retornando ao diretório Alice:

    cd ../Alice
    
    
  6. Agora, abra index.html e insira a seguinte linha logo após a marca <body> na linha 8:

    <nav><a href="./index.html">home</a></nav>
    

    Depois, salve o arquivo e feche o editor.

  7. Em seguida, abra site.css na pasta CSS e adicione a seguinte linha na parte inferior:

    nav { background-color: #C0D8DF; }
    

    Salve o arquivo e feche o editor.

  8. Agora, vamos supor que Alice receba um email de Pedro informando que ele fez alterações no site. Ela decide efetuar pull das alterações dele antes de fazer commit de suas próprias alterações. (Se Alice já tiver confirmado as alterações dela, ela terá um problema diferente, que será abordado em outro módulo.) Alice executa este comando:

    git pull
    
    
  9. Verifique a saída. Na saída, parece que o Git impediu um problema:

    remote: Counting objects: 3, done.
    remote: Compressing objects: 100% (3/3), done.
    remote: Total 3 (delta 2), reused 0 (delta 0)
    Unpacking objects: 100% (3/3), done.
    From ../Shared
       843d142..2cf6cbf  main     -> origin/main
    Updating 843d142..2cf6cbf
    error: Your local changes to the following files would be overwritten by merge:
            index.html
    Please commit your changes or stash them before you can merge.
    Aborting
    

    O Git avisa que o pull substituirá a versão de Alice de index.html e as alterações dela serão perdidas. Isso porque Pedro modificou index.html também. Se Alice não tivesse alterado index.html, o Git teria feito commit da mesclagem.

  10. Use um comando git diff para ver as alterações que Pedro fez em index.html:

    git diff origin -- index.html
    
    
  11. Verifique a saída. Na saída, fica evidente que as alterações de Alice e as alterações de Pedro não se sobrepõem. Agora, Alice pode armazenar em stash as alterações dela.

    git stash salva o estado da árvore de trabalho e do índice fazendo alguns commits temporários. Considere o stash como uma maneira de salvar seu trabalho atual enquanto você faz alguma outra coisa, sem fazer um commit "real" nem afetar o histórico do repositório.

    Na realidade, Alice deveria ter armazenado em stash as alterações ou feito commit delas antes de tentar efetuar pull. O pull para uma árvore de trabalho "suja" é arriscado, pois pode executar ações das quais você não poderá recuperar com facilidade.

    Use o seguinte comando para aplicar stash às alterações de Alice:

    git stash
    
    
  12. Verifique a saída. Ele será semelhante a este exemplo:

    Saved working directory and index state WIP on main: 95bbc3b Change background color to light blue
    HEAD is now at 95bbc3b Change background color to light blue
    
  13. Agora, é seguro para Alice efetuar pull e, depois disso, remover o stash mais recente da pilha, que é organizado como uma pilha. (Na realidade, git stash é abreviatura de git stash push. Isso é muito parecido com a pilha em que você coloca as faturas que você ainda não pagou.) Execute estes comandos:

    git pull
    git stash pop
    
    

    A remoção do stash mais recente da pilha mescla as alterações. Se as alterações se sobrepuserem, poderá haver um conflito. Saiba como resolver essas situações em um módulo mais avançado do Git no Microsoft Learn.

  14. Verifique a saída. Alice verá esta saída, que informa que a mesclagem foi bem-sucedida e que as alterações estão de volta, mas que ainda não foram preparadas para commit:

    Auto-merging index.html
    On branch main
    Your branch is up-to-date with 'origin/main'.
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
            modified:   CSS/site.css
            modified:   index.html
    
    no changes added to commit (use "git add" and/or "git commit -a")
    Dropped refs/stash@{0} (0cfb7b75d56611d9fc6a6ab660a51f5582b8d9c5)
    

    Neste ponto, ela pode continuar trabalhando ou apenas fazer commit e efetuar push das alterações. Vamos fazer outra alteração como Alice, atribuindo rodapés no mesmo estilo das barras de navegação.

  15. Abra site.css na pasta CSS e substitua a terceira linha, aquela que define o estilo de elementos <nav>, por esta regra CSS compartilhada. Em seguida, como de costume, salve as alterações e feche o editor.

    nav, footer { background-color: #C0D8DF; }
    
  16. Agora, faça commit das alterações e efetue push delas para o repositório compartilhado:

    git commit -a -m "Stylize the nav bar"
    git push
    
    

    O site atualizado agora está no repositório compartilhado.

  17. Conclua retornando ao diretório do projeto e efetuando um pull:

    cd ../Cats
    git pull
    
    
  18. Abra index.html (aquele no diretório do projeto) para confirmar se as alterações feitas por Pedro e Alice estão presentes no repositório local. Verifique se index.html tem o código mais atualizado:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset='UTF-8'>
        <title>Our Feline Friends</title>
        <link rel="stylesheet" href="CSS/site.css">
      </head>
      <body>
        <nav><a href="./index.html">home</a></nav>
        <h1>Our Feline Friends</h1>
        <p>Eventually we will put cat pictures here.</p>
        <footer><hr>Copyright (c) 2021 Contoso Cats</footer>
      </body>
    </html>
    
  19. No momento, seu repositório e o repositório de Alice estão sincronizados, mas o de Pedro não. Conclua atualizando Pedro também:

    cd ../Bob
    git pull
    
    

Os três repositórios estão agora em alinhamento. O repositório compartilhado é a única fonte de verdade para todos os usuários, e todos os pushes e pulls são direcionados para o repositório compartilhado.

Caso você esteja curioso sobre a aparência do site, esta é uma visualização:

Screenshot of the rendered Cats website.

Se desejar, baixe seus arquivos para visualizá-los localmente:

  1. Compacte a pasta Cats:

    cd ..
    zip -r Cats.zip Cats
    
    
  2. Baixe o arquivo compactado:

    download Cats.zip
    
    
  3. Agora, descompacte-o no computador local e abra index.html para vê-lo.