Wiki Ubuntu-it

Indice
Partecipa
FAQ
Wiki Blog
------------------
Ubuntu-it.org
Forum
Chiedi
Chat
Cerca
Planet
  • Pagina non alterabile
  • Informazioni
  • Allegati

Versione 2 del 06/12/2014 12.49.44

Nascondi questo messaggio


Problemi in questa pagina? Segnalali in questa discussione

Introduzione

In questa pagina vengono mostrati gli strumenti di Git che rendono possibile il lavoro di più persone ad un progetto. Per fare questo verrà simulata in locale una situazione analoga a quella in cui si utilizzi un repository remoto.

Per poter seguire la seguente guida si presuppone:

  • di aver creato il progetto gitproject come indicato;

  • di aver elaborato il progetto come mostrato nelle pagine sul Commit e sul Branching.

Verrà creato un nuovo repository gitproject_2 che simulerà il repository locale, mentre gitproject simulerà il repository remoto.

Clonazione repository

  1. Creare una nuova cartella in cui vogliamo creare il nuovo repository:

    mkdir ~/gitproject_2
    cd ~/gitproject_2
  2. Clonare il repository gitproject nella cartella corrente ".":

    git clone ~/gitproject .

    Il comando sarebbe stato del tutto analogo anche se gitproject si fosse trovato su di un server esterno al proprio pc.

  3. Consultare il log:

    git lg

    che restituirà:

    *   f61b2e2 (HEAD, origin/master, origin/HEAD, master) - user : Merge branch 'gp-1' (4 minutes ago)
    |\  
    | * d8b610a (origin/gp-1) - user : Modificato codice per issue gp-1. (11 minutes ago)
    * | e4064d8 - user : Aggiunta cartella documentazione. (6 minutes ago)
    |/  
    * 1412239 - user : Aggiunta data in stampa. (15 minutes ago)
    * e1e5a46 - user : Aggiunti sorgenti e Makefile (18 minutes ago)
    * e9ea39b - user : README aggiunto (25 minutes ago)

    Il log è quasi uguale a quello originale. Si nota la presenza di altri branch:

    • origin/master

    • origin/HEAD

    • origin/gp-1

    Questi sono i branch del repository remoto, che sono materialmente quelli creati nel repository originale. origin è il nome di default che Git da a un repository remoto,.

  4. Attraverso il comando remote elencare i repository remoti:

    git remote

    che restituirà:

    origin
    Allo stato attuale ne risulta uno solo, quello clonato.

    Git puo avere più repository remoti associati al repository locale. Questo permette molta flessibilità, ma al momento verrà ignorato questo aspetto.

  5. Attraverso il comando branch elencare i branch:

    git branch

    che risulterà:

    * master

    solamente un branch locale, master, sincronizzato con il master remoto (più precisamente nel punto in cui punta HEAD remoto).

Aggiunta manuale remote

Il secondo metodo consiste nell'aggiungere manualmente il repository remoto a quello attuale.

Creiamo quindi un repository vuoto:

mkdir /home/user/gitproject_3
cd /home/user/gitproject_3
git init
Initialized empty Git repository in /home/user/gitproject_3/.git/

Se vediamo la lista dei repository remoti, ovviamente e' vuota:

git remote

Aggiungiamo quindi il repository remoto, tramite il comando remote add:

git remote add origin /home/user/gitproject
git remote
origin

Proviamo a vedere il log:

git lg
fatal: bad default revision 'HEAD'

Il repository e' vuoto!

ls -altr
drwxrwxr-x 22 user group 4096 Dec  4 15:06 ..
drwxrwxr-x  3 user group 4096 Dec  4 15:06 .
drwxrwxr-x  7 user group 4096 Dec  4 15:07 .git

Questo perche' e' stato aggiunto il repository remoto, ma non abbiamo ancora fatto la sincronizzazione. Per poter sincronizzare il repository locale con quello remoto, occorre scaricare le modifiche. Questo viene fatto in due modi.

Fetch e Pull

Si vuole prendere il contenuto del repository remoto e sincronizzare quello locale, in maniera da poter prendere le modifiche remote. Il comando fetch permette di scaricare in locale le modifiche remote, ma NON di applicarle.

git fetch origin
remote: Counting objects: 23, done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 23 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (23/23), done.
From /home/user/gitproject
 * [new branch]      gp-1       -> origin/gp-1
 * [new branch]      master     -> origin/master

Abbiamo scaricato le modifiche remote, ma se guardiamo il contenuto della cartella, risulta essere ancora vuota:

ls -altr
drwxrwxr-x 22 user group 4096 Dec  4 15:06 ..
drwxrwxr-x  3 user group 4096 Dec  4 15:06 .
drwxrwxr-x  7 user group 4096 Dec  4 15:09 .git

Questo perche' abbiamo scaricato le modifiche (che stanno dentro .git) ma non abbiamo ancora sincronizzato il tutto. Dal log possiamo vedere meglio quello che e' successo:

git lg
*   f61b2e2 (origin/master) - user : Merge branch 'gp-1' (10 minutes ago)
|\  
| * d8b610a (origin/gp-1) - user : Modificato codice per issue gp-1. (17 minutes ago)
* | e4064d8 - user : Aggiunta cartella documentazione. (12 minutes ago)
|/  
* 1412239 - user : Aggiunta data in stampa. (21 minutes ago)
* e1e5a46 - user : Aggiunti sorgenti e Makefile (23 minutes ago)
* e9ea39b - user : README aggiunto (31 minutes ago)

Come possiamo vedere, ci sono i repository remoti, ma non quello locale su cui ci troviamo. E, dato che in quello locale non abbiamo ancora fatto niente, la nostra directory e' vuota.

Effettuamo allora il merge del branch locale con quello remoto, come abbiamo visto precedentemente, e vediamo che succede:

git merge origin/master
git lg
*   f61b2e2 (HEAD, origin/master, master) - user : Merge branch 'gp-1' (11 minutes ago)
|\  
| * d8b610a (origin/gp-1) - user : Modificato codice per issue gp-1. (18 minutes ago)
* | e4064d8 - user : Aggiunta cartella documentazione. (13 minutes ago)
|/  
* 1412239 - user : Aggiunta data in stampa. (22 minutes ago)
* e1e5a46 - user : Aggiunti sorgenti e Makefile (24 minutes ago)
* e9ea39b - user : README aggiunto (32 minutes ago)

Come possiamo vedere, adesso i due branch sono allineati (puntano allo stesso commit). D'altronde, se vediamo il contenuto della cartella, possiamo vedere che e' aggiornato:

ls -altr
total 32
drwxrwxr-x 22 user group 4096 Dec  4 15:06 ..
drwxrwxr-x  2 user group 4096 Dec  4 15:11 src
-rw-rw-r--  1 user group   16 Dec  4 15:11 README
-rw-rw-r--  1 user group  258 Dec  4 15:11 Makefile
-rw-rw-r--  1 user group   10 Dec  4 15:11 .gitignore
drwxrwxr-x  8 user group 4096 Dec  4 15:11 .git
drwxrwxr-x  2 user group 4096 Dec  4 15:11 doc
drwxrwxr-x  5 user group 4096 Dec  4 15:11 .

Potevamo eseguire il tutto con un unico comando, pull. Questo racchiude in se' il fetch ed il merge, ed e' il comando solitamente utilizzato in questi casi. Ricreiamo il repository e vediamo che succede col pull (in una nuova cartella vuota). Il comando pull richiede il nome del repository remoto e il branch di cui fare l'update:

mkdir /home/user/gitproject_4
cd /home/user/gitproject_4
git init
Initialized empty Git repository in /home/user/gitproject_4/.git/
git remote add origin /home/user/gitproject
git pull origin master
remote: Counting objects: 23, done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 23 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (23/23), done.
From /home/user/gitproject
 * branch            master     -> FETCH_HEAD
git lg
*   f61b2e2 (HEAD, origin/master, master) - user : Merge branch 'gp-1' (15 minutes ago)
|\  
| * d8b610a - user : Modificato codice per issue gp-1. (22 minutes ago)
* | e4064d8 - user : Aggiunta cartella documentazione. (17 minutes ago)
|/  
* 1412239 - user : Aggiunta data in stampa. (26 minutes ago)
* e1e5a46 - user : Aggiunti sorgenti e Makefile (28 minutes ago)
* e9ea39b - user : README aggiunto (36 minutes ago)

Abbiamo quindi creato un repository, e sincronizzato il suo contenuto con un repository remoto.

Pubblicazione modifiche locali

Possiamo a questo punto effettuare delle modifiche nel nostro nuovo repository:

sed -i '4 a \\tstd::cout << "Modifica da un altro repository" << std::endl;' src/main.cpp
cat src/main.cpp
#include <iostream>
int main() {
    std::cout << "Thu Dec  4 14:48:20 CET 2014: Benvenuti su Git!" << std::endl;
    std::cout << "Issue gp-1 implementata" << std::endl;
    std::cout << "Modifica da un altro repository" << std::endl;
    return 0;
}
git commit -a -m "Aggiunta riga di output."
[master 0ed9a58] Aggiunta riga di output.
 1 file changed, 1 insertion(+)
git lg
* 0ed9a58 (HEAD, master) - user : Aggiunta riga di output. (15 seconds ago)
*   f61b2e2 (origin/master) - user : Merge branch 'gp-1' (23 minutes ago)
|\  
| * d8b610a (origin/gp-1) - user : Modificato codice per issue gp-1. (30 minutes ago)
* | e4064d8 - user : Aggiunta cartella documentazione. (26 minutes ago)
|/  
* 1412239 - user : Aggiunta data in stampa. (34 minutes ago)
* e1e5a46 - user : Aggiunti sorgenti e Makefile (37 minutes ago)
* e9ea39b - user : README aggiunto (44 minutes ago)

Abbiamo creato un nuovo commit, e dal log possiamo vedere che i due branch master, quello locale e quello remoto, non sono piu' (ovviamente) allineati. Per inviare al repository remoto le mostre modifiche, occorre utilizzare il comando push, specificando sempre il repository remoto e i branch da voler sincronizzare:

git push origin master
Counting objects: 7, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 395 bytes, done.
Total 4 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
To /home/user/gitproject
   f61b2e2..0ed9a58  master -> master

A questo punto abbiamo mandato nel repository remoto le nostre modifiche, in modo tale che gli altri utenti del repository, una volta sincronizzati con quello remoto, possano percepire le nostre modifiche.

Errore push

A questo punto si potrebbe ottenere il seguente messaggio di errore:

remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error: 
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error: 
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To ../gitproject/
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to '/home/user/gitproject'

Questo perche' il nostro repository remoto non e' di tipo bare. Al momento ignoriamo questo avviso e, per poter effettuare il push, digitare il seguente comando:

git config --global receive.denyCurrentBranch ignore

E poi rieseguire il push. Quando non e' piu' necessario settare lo stesso valore a refuse:

git config --global receive.denyCurrentBranch refuse

per ripristinare lo stato originale.

Per essere sicuri di aver fatto tutto correttamente, andiamo ad uno dei repository creato in precedenza:

cd /home/user/gitproject_3

Ed effettuiamo il pull per risincronizzarci col server remoto, che a questo punto avra' le nostre modifiche:

git pull origin master
From /home/user/gitproject
 * branch            master     -> FETCH_HEAD
Updating f61b2e2..0ed9a58
Fast-forward
 src/main.cpp |    1 +
 1 file changed, 1 insertion(+)
git lg
* 0ed9a58 (HEAD, origin/master, master) - user : Aggiunta riga di output. (4 minutes ago)
*   f61b2e2 - user : Merge branch 'gp-1' (27 minutes ago)
|\  
| * d8b610a (origin/gp-1) - user : Modificato codice per issue gp-1. (34 minutes ago)
* | e4064d8 - user : Aggiunta cartella documentazione. (30 minutes ago)
|/  
* 1412239 - user : Aggiunta data in stampa. (38 minutes ago)
* e1e5a46 - user : Aggiunti sorgenti e Makefile (41 minutes ago)
* e9ea39b - user : README aggiunto (48 minutes ago)

Ulteriori risorse


CategoryProgrammazione