Esercizio - Collaborare usando un repository condiviso

Completato

Il pull diretto dal repository di un altro utente riesce a condizione che ci si trovi entrambi nella stessa rete. Tuttavia, si tratta di un processo inefficace e la maggior parte dei collaboratori non si trova nella stessa rete. È preferibile configurare un repository centrale da cui e verso cui tutti i collaboratori possano eseguire il pull e il push.

Si supponga di parlare del proprio progetto a Bob, un amico sviluppatore, e che Bob chieda di partecipare. Questo è un caso ideale in cui configurare un repository centrale, denominato anche repository bare.

Creare un repository bare

È necessario un repository che non abbia un albero di lavoro. Un repository bare presenta diversi vantaggi rispetto a un albero di lavoro:

  • Senza un albero di lavoro, tutti possono eseguire il push delle modifiche senza doversi preoccupare del ramo estratto.
  • È facile per Git rilevare quando un altro utente ha eseguito il push di modifiche che possono essere in conflitto con le proprie.
  • Un repository condiviso può essere usato da un numero qualsiasi di sviluppatori. Con un repository bare, è necessario identificare solo il repository condiviso, senza sapere nulla di quelli di tutti gli altri collaboratori dai quali può essere necessario eseguire il pull.
  • Posizionando il repository condiviso in un server accessibile a tutti, non è necessario preoccuparsi di firewall e autorizzazioni.
  • Non sono necessari account separati nel server, perché Git tiene traccia di chi ha eseguito ogni commit. GitHub ha milioni di utenti che condividono tutti l'account git. Tutti usano il protocollo di rete crittografico Secure Shell (SSH) e gli utenti vengono distinti tramite le rispettive chiavi pubbliche.

La creazione di un repository bare per la condivisione è semplice:

  1. Creare una nuova directory denominata Shared.git allo stesso livello delle directory Alice e Cats in cui inserire il repository bare:

    cd ..
    mkdir Shared.git
    cd Shared.git
    
    

    Il nome della directory non è importante, ma in questi esercizi vi si farà riferimento come directory Shared.git o semplicemente directory shared.

    L'assegnazione del nome Shared.git alla directory segue la lunga tradizione di assegnare ai repository bare un nome che termina con .git per distinguerli dagli alberi di lavoro. Si tratta di una convenzione, non di un requisito.

  2. Usare ora il comando seguente per creare un repository bare nella directory condivisa:

    git init --bare
    
    
  3. Quando un repository è ancora bare, non è possibile usare il comando git checkout per impostare il nome del ramo predefinito. A questo scopo, è possibile modificare il ramo HEAD in modo che punti a un ramo diverso, in questo caso il ramo main:

    git symbolic-ref HEAD refs/heads/main
    
    
  4. Il passaggio successivo consiste nell'inserire il contenuto del proprio repository nel repository condiviso. Usare questi comandi per tornare alla directory del progetto in cui è archiviato il repository, configurare un repository remoto origin ed eseguire un push iniziale:

    cd ../Cats
    git remote add origin ../Shared.git
    git push origin main
    
    
  5. Controllare l'output di . L'output indica che l'operazione è riuscita:

    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. I rami push e pull devono usare il ramo main di origin per impostazione predefinita, come se il repository fosse stato creato tramite clonazione sin dall'inizio. Ma prima di tutto, è necessario indicare a Git il ramo di cui tenere traccia.

    git branch --set-upstream-to origin/main
    
    
  7. Verificare questo output:

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

    Git genera un errore se si tenta di eseguire questo comando prima del push iniziale, perché il nuovo repository non ha rami. Git non può tenere traccia di un ramo che non esiste. In background Git cerca in .git/refs/remotes/origin un file denominato trunk.

Eseguire la configurazione per i collaboratori

Nel passaggio successivo Bob deve clonare il repository bare e quindi Alice deve impostare il repository origin nel proprio repository come destinazione del repository condiviso per le operazioni di push e pull.

  1. Creare una directory denominata Bob che sia di pari livello rispetto alla directory del progetto e quindi passare alla directory Bob:

    cd ..
    mkdir Bob
    cd Bob
    
    
  2. Clonare ora il repository condiviso, assicurandosi di includere il punto alla fine del comando:

    git clone ../Shared.git .
    
    
  3. Attualmente il repository di Alice è configurato per il push e il pull da e verso il proprio repository. Usare i comandi seguenti per passare alla directory Alice e modificare origin in modo che punti al repository condiviso:

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

Iniziare a collaborare

Ora che Bob può collaborare al sito Web, decide di aggiungere un piè di pagina in fondo alla pagina. Assumere il ruolo di Bob e Alice per alcuni istanti e apprendere le nozioni di base della collaborazione.

  1. Per iniziare, passare alla directory Bob e operare come Bob:

    cd ../Bob
    git config user.name Bob
    git config user.email bob@contoso.com
    
    
  2. Aprire index. html e sostituire l'elemento <hr> con questa riga (presente alla fine dell'elemento <body>):

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

    Salvare quindi il file e chiudere l'editor.

  3. Eseguire il commit e il push delle modifiche nel repository remoto origin:

    git commit -a -m "Put a footer at the bottom of the page"
    git push
    
    
  4. Controllare l'output di . Se viene visualizzato un avviso come nell'esempio seguente, non è un problema. L'avviso comunica semplicemente agli utenti una variazione rispetto ai comportamenti predefiniti di Git. Per non visualizzare più l'avviso, è possibile eseguire 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. Mentre Bob sta modificando il sito, anche Alice sta facendo la stessa cosa. Alice decide di aggiungere una barra di spostamento alla pagina. Per questa aggiunta, Alice deve modificare due file: index.html e site.css. Per iniziare, tornare alla directory Alice:

    cd ../Alice
    
    
  6. Aprire ora index.html e inserire la riga seguente dopo il tag <body> alla riga 8:

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

    Salvare quindi il file e chiudere l'editor.

  7. Aprire quindi site.css nella cartella CSS e aggiungere la riga seguente alla fine:

    nav { background-color: #C0D8DF; }
    

    Salvare il file e chiudere l'editor.

  8. Si supponga ora che Alice riceva un messaggio e-mail da Bob che segnala che Bob ha apportato modifiche al sito. Alice decide di eseguire il pull delle modifiche di Bob prima del commit delle sue modifiche. Se Alice avesse già eseguito il commit delle proprie modifiche, avrebbe avuto un problema diverso, che verrà illustrato in un altro modulo. Alice esegue questo comando:

    git pull
    
    
  9. Controllare l'output di . Dall'output sembra che Git abbia evitato un 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
    

    Git avvisa che il pull sovrascriverebbe la versione di Alice di index.html e le modifiche di Alice andrebbero perse. Ciò è dovuto al fatto che anche Bob ha modificato index.html. Se Alice non avesse modificato index.html, Git avrebbe eseguito il commit del merge.

  10. Usare un comando git diff per visualizzare le modifiche apportate da Bob a index.html:

    git diff origin -- index.html
    
    
  11. Controllare l'output di . Dall'output è evidente che le modifiche di Alice e quelle di Bob non si sovrappongono. Alice può ora accantonare le proprie modifiche.

    git stash salva lo stato dell'albero di lavoro e dell'indice eseguendo un paio di commit temporanei. È possibile pensare all'accantonamento come un modo per salvare il lavoro corrente mentre si esegue un'altra operazione, senza eseguire un commit "reale" o influire sulla cronologia del repository.

    In realtà, Alice avrebbe dovuto accantonare le modifiche o eseguirne il commit prima di provare a eseguire il pull. Il pull in un albero di lavoro modificato ma non salvato è rischioso, perché può comportare operazioni da cui non è facile eseguire il ripristino.

    Usare il comando seguente per accantonare le modifiche di Alice:

    git stash
    
    
  12. Controllare l'output di . Sarà simile a questo esempio:

    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. Alice può ora eseguire il pull in tutta sicurezza, quindi può "prelevare" le modifiche accantonate, organizzate come stack. git stash è infatti la versione abbreviata di git stash push. Lo stack è molto simile alla pila in cui vengono collocate le fatture ancora da pagare. Eseguire questi comandi:

    git pull
    git stash pop
    
    

    Il prelievo delle modifiche accantonate comporta il merge delle modifiche. Se le modifiche si sovrappongono, può verificarsi un conflitto. Le informazioni su come risolvere queste situazioni sono disponibili in un modulo più avanzato su Git di Microsoft Learn.

  14. Controllare l'output di . Alice visualizzerà questo output, che indica che il merge è riuscito e che le modifiche sono state ripristinate, ma non ancora preparate per il 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)
    

    A questo punto Alice può continuare a lavorare o semplicemente eseguire il commit e il push delle modifiche. Apportare un'altra modifica nelle vesti di Alice assegnando ai piè di pagina lo stesso stile delle barre di spostamento.

  15. Aprire site.css nella cartella CSS e sostituire la terza riga, che definisce lo stile degli elementi <nav>, con questa regola CSS condivisa. Quindi, come di consueto, salvare le modifiche e chiudere l'editor.

    nav, footer { background-color: #C0D8DF; }
    
  16. Eseguire ora il commit e il push delle modifiche nel repository condiviso:

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

    Il sito aggiornato si trova ora nel repository condiviso.

  17. Terminare tornando alla directory del progetto ed eseguendo un pull:

    cd ../Cats
    git pull
    
    
  18. Aprire index.html (quello nella directory del progetto) per verificare che le modifiche apportate da Bob e Alice siano presenti nel repository locale. Verificare che index.html includa il codice più aggiornato:

    <!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. Al momento, il proprio repository e quello di Alice sono sincronizzati, ma quello di Bob non lo è. Per finire, aggiornare anche il repository di Bob:

    cd ../Bob
    git pull
    
    

Tutti e tre i repository sono ora allineati. Il repository condiviso è l'unica origine di dati reali per tutti gli utenti e tutte le operazioni di push e pull avvengono nel repository condiviso.

Se si vuole sapere quale aspetto avrà il sito Web, ecco un'anteprima:

Screenshot of the rendered Cats website.

Se si vuole, è possibile scaricare i file per visualizzarne un'anteprima in locale:

  1. Comprimere la cartella Cats:

    cd ..
    zip -r Cats.zip Cats
    
    
  2. Scaricare il file compresso:

    download Cats.zip
    
    
  3. Decomprimere ora il file nel computer locale e aprire index.html per verificare di persona.