Differences between revisions 2 and 3
Revision 2 as of 2011-01-07 02:49:26
Size: 3748
Editor: ?skizzhg
Comment: header
Revision 3 as of 2011-01-07 12:29:43
Size: 16333
Editor: ?ErmenegildoFiorito
Comment: commiting b4 apocalypse, draft 2
Deletions are marked like this. Additions are marked like this.
Line 51: Line 51:

 * L' '''area di lavoro''' è composta dai file presenti nella nostra cartella git
 * L' '''index''' e '''repository''', invece, sono contenuti all'interno di {{{./.git/}}} -- qui è dove tutti i repository git risiedono, ed è sufficiente per ricreare il contenuto delle cartelle. Andando oltre, possiamo dire che l' ''index'' è come una temporanea area di sosta, dove tu puoi aggiungere i file prima di eseguire il commit. Una volta che il commit è stato eseguito, il contenuto andrà all'interno del repository, e l'azione compiuta verrà conservata nella sua cronologia, se tu non esegui il commit, puoi rimuovere i file dall'index senza lasciare traccia nella cronologia del repository.


== Pratica ==


=== Creare un repository ===

Per la parte pratica, ho voluto usare un progetto reale, anzichè creare qualche repository. Ho scelto di usare "GNU Hello", scaricalo da [[http://ftp.gnu.org/gnu/hello/hello-2.6.tar.gz]]. Noi creeremo un repository da questo codice sorgente.

Scarichiamo il tarball:

{{{
$ wget http://ftp.gnu.org/gnu/hello/hello-2.6.tar.gz
}}}

Una volta fatto, spacchettiamolo:

{{{
$ tar zxvf hello-2.6.tar.gz
}}}

Questo comando creerà la cartella {{{hello-2.6/}}}. Adessim entriamo nella cartella ed iniziamo a giocare con ''git'' :)
Prima di tutto, abbiamo bisogno di configurare il nostro username e la nostra e-mail. Queste informazioni verranno usate nei nostri commit, e saranno visibili nella cronologia del repository. Per fare ciò, usiamo {{{git config}}}. In particolare, visto che siamo dei principianti, vogliamo settare username ed e-mail in modo globale. Quindi lanciamo i comandi:

{{{
$ git config --global user.name "Debian Woman Attendant"
$ git config --global user.email "attendant@debian.org"
}}}

Naturalmente usa i tuoi dati :)

L'opzione {{{--global}}} fa in modo che il cambiamento sia globale, ad esempio per ogni repository git sul tuo computer lui scrivere le informazioni in {{{~/.gitconfig}}}. Controlla questo file, dopo che avrai eseguito questi due comandi. Vedrai le informazioni che hai fornito.

L'username e l'e-mail possono anche essere cambiate in base al repository: in questo caso, puoi farlo dopo aver creato il repository, e senza l'opzione {{{--global}}}. Senza {{{--global}}}, lui inserirà le informazioni localmente in {{{./.git/config}}}.


Abbiamo impostato l'username e l'e-mail. Ora, abbiamo bisogno di creare il repository git. Quindi abbiamo una cartella {{{hello-2.6/}}}: entriamoci ed lanciamo:

{{{
$ git init
}}}
Il risultato sarà qualcosa di simile:

{{{
Initialized empty Git repository in /tmp/dw/hello-2.6/.git/
}}}

{{{git init}}} semplicemente crea una cartella {{{.git/}}}, come alcuni valori di default. Per vedere lo stato di un repository, lancia:

{{{
$ git status
}}}

Ti mostrarà i file monitorati e non, e lo stato dell'index. In più, ti mostrerà in qualche ''branch'' sei (spiegerò i branch più tardi).

=== Indexing ===

Non abbiamo ancora nulla nel repository. Quindi aggiungiamo il codice sorgente:

{{{
$ git add .
}}}

Il "." è una sintassi dei sistemi Unix-like -- significa "cartella corrente". Quindi in questo modo aggiungiamo tutto il contenuto. Ora, controlla {{{git status}}} di nuovo. Vedrai che qualcosa è cambiato. Quello che vedi ora è lo stato di ''index''.

Noi possiamo ancora rimuovere file o cartelle dall'index, senza lasciare tracce nella cronologia. Facciamolo! rimuoviamo il file
We could still remove things from the index, without leaving traces in the repository history. Let's do it! Let's remove {{{AUTHORS}}} dall'index e rimettiamo nello stato di "non tracciato"

{{{
$ git rm --cached AUTHORS
}}}

Ora dai di nuovo uno sguardo a {{{git status}}}. Vedrai ''Changes to be committed''(cambiamenti che devono essere committati) (l'index) e ''Untracked files'' (file non tracciati).

=== Committing ===

Ora vogliamo '''committare'''i file nell'index: questo creerà un commit, con un hash, e verrà conservato nella cronologia del repository. Lanciamo:

{{{
$ git commit
}}}

Questo comando aprirà il tuo {{{$EDITOR}}} (il mio è {{{nano}}}, controlla il tuo), dove tu dovrai scrivere un messaggio di commit. Se tu non ne scrivi uno, il commit verrà annullato (si, tu '''devi''' inserire un messaggio di commit)

Chiamiamolo "Commit iniziale". Ora, lancia di nuovo {{{git status}}} . I file dall'index sono spariti! Sono stati committati all'interno del repository, e il log è stato conservato.

Puoi vedere i log con:

{{{
$ git log
}}}
Ti verrà mostrato il committer(l'autore del commit, con le informazioni inserite prima), il timestamp, e l'hash del commit.

Puoi anche vedere l'ultimo commit con:

{{{
$ git show
}}}

Aprirà automaticamente {{{$PAGER}}} e mostrerà il contenuto del tuo ultimo commit. {{{git show}}} accetta anche un hash come argomento. Il mio commit ha hash: 11aab8486d20490b16b1b7d847e1cb1e4f7aa2fe . Che è differente dal uno dei tuoi. Non è necessario scrivere l'hash completo --normalmente bastano i primi 7,8 caratteri. Quindi possiamo lanciare:

{{{
$ git show 11aab848
}}}

{{{git}}} supporta anche un numero di nomi simbolici, ma non verranno spiegati ora in quanto credo non siano argomenti "di base" da poter essere spiegati in questa sessione (Sto parlando di {{{HEAD}}}, {{{HEAD^}}}, {{{HEAD~2}}} e così via)

Quindi, abbiamo rimosso {{{AUTHORS}}} dal nostro repository... poveracci! nessun merito al loro lavoro! Correggiamo No credit for their work! possiamo correggere questo problema:

{{{
$ git add AUTHORS
$ git commit -m 'Also add AUTHORS'
}}}

{{{-m}}} è una scorciatoia per il ''messagio'' -- evita così di aprire {{{$EDITOR}}}

Ora, abbiamo bisogno di moficare alcuni file, guarda le differenze, e commitale. Prima pretendiamo che abbiamo scritto un pezzo di codice.

Aggiungiamo il nostro nome al file {{{AUTHORS}}} :) E aggiungiamo anche qualcosa a "ChangeLog". Quello che vuoi, è solo un esempio.

Ora, {{{git status}}}. Vedrai le prime due linee indicate con ''modified''(modificato). Puoi vedere le differenze che hai introdotto:

{{{
$ git diff
}}}

(Opzionalmente, {{{git diff filename}}} mostrerà solo le differenze in quel file.)

Se sei felice con quste modifiche, committiamo!.
If you're happy with the diff, let's commit it. È possibile lanciare {{{git add}}} uno per uno e committare {{{git commit}}}
oppure usare soltanto:

{{{
$ git commit -a -m "Messaggio a piacere"
}}}

L'argomento {{{-a}}} aggiungerà tutto all'index ( ma solo i file tracciati, quelli non tracciati non saranno toccati. Vedrai:

{{{
[master 3295347] Messaggio a piacere
2 files changed, 5 insertions(+), 0 deletions(-)
}}}

''master'' è il branch in cui siamo ora. La stringa dopo di quello è l'hash del commit --puoi usarla in molti comandi ({{{git show <commit>}}}, {{{git log <commit>}}}, etc). E dopo, vi è il messaggio di commit e le statistiche dei cambiamenti apportati (diffstats).

=== Branching ===

Cos'è un '''branch'''?

Pensa al repository git come ad un fiume. Ad un certo punto, lo sviluppo può divergere dal "flusso principale" e rimanere solo lì, oppure
Think of your git repository as a river. At a certain point, development can diverge from the ''main flow'' and it can stay on its own, oppure unirsi di nuovo al fiume originale. Ora il nostro ''master'' è ''il fiume principale".

Creiamo un branch, chiamiamolo ''debian'':

{{{
$ git branch debian
}}}

Per cambiare a questo nuovo branch lancia:

{{{
$ git checkout debian
}}}

Una scorciatoia per entrambi i comandi è:

{{{
$ git checkout -b debian
}}}

Ok, ora siamo nel branch ''debian''. Per controllare se è vero, esegui {{{git branch}}}, senza argomenti. Ti mostrerà i branch locali, e un {{{*}}} anteposto ti mostrerò quello in cui sei ora.

Per tornare indietro al branch principale, esegui: {{{git checkout master}}}.

Ma per il momento rimarremo sul branch ''debian'': {{{*debian}}}.
All'interno di questo branch faremo il lavoro di pacchettizzazione.

Quindi, creiamo una cartella {{{debian/}}}. Se la cartella è vuota, {{{git status}}} non la mostrerà, è il comportamento previsto: ''git'' non tiene traccia delle cartelle vuote. Per ingannarlo a fare queto puoi aggiungere un file vuoto alla cartella. Io normalmente aggiungo un {{{.gitignore}}} (è un file speciale usato da git), per lasciargli tracciare una cartella vuota.
Quindi eseguiamo questo:

{{{
$ mkdir debian
$ touch debian/.gitignore
}}}

Ora {{{git status}}} mostrerà la non-tracciata {{{debian/}}}. Aggiungila e committala.

Ora torniamo al branch ''master''

{{{
$ git checkout master
}}}

Ora vogliamo far divergere questi due branch, per simulare un branch reale: cambia tutti i file che vuoi, e committa i cambiamenti.

Puoi usare un'interfaccia grafica ( come ad esempio ''gitg'' o ''gitk''), o qualcosa da linea di comando ({{{git show-branch}}}) Per vedere come i due branch sono divergenti. Visto che le gui sono facili da usare, useremo la riga di comando :D)

{{{
$ git show-branch
}}}

Vedrai che i due branch hanno un commit inziale in comune, ma apparte questo hanno commit differenti. Quindi uniamo i cambiamenti di "debian" in "master"

{{{
$ git merge debian
}}}

Vedrai qualcosa come:

{{{
Merge made by recursive.
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 debian/.gitignore
}}}


E ora ci saranno dei "conflitti". Se in ''debian'' abbiamo cambiato uno dei file cambiati prima del merge, questi potrebbero andare in conflitto.
Sarebbe utile lanciare {{{git mergetool}}} dopo il merge, per risolvere i conflitti. Userà uno dei possibili programmi per gestire i conflitti. Non voglio entrare nei dettagli --in ogni caso è sempre meglio risolvere i conflitti manualmente.

Abbiamo unito ''debian'' in ''master''. Ora vediamo i log, dovresti vedere qualcosa come:

{{{
commit cdfd20167aa05f74f4785ef7aa03355d51add5b3
Merge: 7e9ff3a 2ba81df
Author: David Paleino <dapal@debian.org>
Date: Thu Nov 25 23:45:28 2010 +0100

    Merge branch 'debian'

commit 7e9ff3a18dc114b4ce1e1a96f1dd3ecd696f064d
Author: David Paleino <dapal@debian.org>
Date: Thu Nov 25 23:43:49 2010 +0100

    New author

commit 2ba81dfaeb919e6a0c634be54fe363b11487d65a
Author: David Paleino <dapal@debian.org>
Date: Thu Nov 25 23:42:42 2010 +0100

    add debian/

commit 3295347b1dbd7b5925dca7fcc6858af51a710ada
Author: David Paleino <dapal@debian.org>
Date: Thu Nov 25 23:32:55 2010 +0100

    Some message

commit f6aa148a5ce1331de6d17e770a8efbb98ad32344
Author: David Paleino <dapal@debian.org>
Date: Thu Nov 25 23:11:57 2010 +0100

    Also add AUTHORS

commit 11aab8486d20490b16b1b7d847e1cb1e4f7aa2fe
Author: David Paleino <dapal@debian.org>
Date: Thu Nov 25 23:03:42 2010 +0100

    Initial commit
}}}

=== Ripristino ===

L'ultima cosa che voglio spiegare per quanto riguarda la parte della guida ''in locale'' è '''{{{git revert}}}'''.

Suppomiamo che io trovi qualcosa che non mi piace nel mio {{{git log}}}. Per esempio diciamo che è il (mio) commit 2ba81dfaeb919e6a0c634be54fe363b11487d65a , quello con cui ho aggiunto la cartella {{{debian/}}} directory. Ricordati che gli hash sono diffenti per ciascuna persona, quindi guarda i log per vedere il tuo.

Dunque, non mi piace. Cosa dovrei fare ora? Posso usare il comando {{{git revert}}}.

Questo comando prende semplicemente il cambiamento (diff) da un commit, e lo applica al contrario, e lascia i conflitti, se ce ne sono, proviamolo:

{{{
$ git revert 2ba81dfaeb919e6a0c634be54fe363b11487d65a
}}}

{{{$EDITOR}}} (''nano'', ''vim'', ecc) si apre di nuovo. C'è un messaggio There is a default commit message; you can leave it as-is, or (better) explain why you're reverting the change. For the sake of simplicity, let's leave the default. Save the message, and quit the editor.

You'll see:

{{{
Finished one revert.
[master 37ce99f] Revert "add debian/"
0 files changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 debian/.gitignore
}}}

This means: a revert is a commit too. With a Committer, an Author, a Timestamp, and a Hash. Ideally, you can revert a revert.
(you shouldn't do it :) )

'''NOTE:''' Reverting a merge is not that easy. You should also specify the mainline parent. Read about the {{{-m}}} switch of {{{git revert}}}. It also has some nasty (IMHO) side-effects, so don't merge if you're not absolutely sure.

Translation(s): English - Italiano



Usare Git

Seminario online tenuto da David Paleino per Debian Women, 25-Nov-2010

Questa è una guida introduttiva all'uso di git. Verranno spiegate le basi per capire il suo funzionamento e il suo uso.

Requisiti

In questa guida si presume che:

  • si conosca l'uso di base della linea di comando e l'utilizzo di un editor di testo a scelta (emacs, vim, gedit, kate, etc.);

Requisiti tecnici:

Introduzione

Cos'è git? Git è un sistema di Controllo di versione distribuito. La parte importante è Controllo di versione -- significa che è un programma che permette di tenere traccia dei cambiamenti dei file e comparare le differenti "versioni", e fare anche un'altra cosa fantastica, come tornare indietro a precedenti versioni di un certo file.

Git viene usato da molti progetti software moderni, quindi è bene conoscere almeno un po' del suo funzionamento. Non c'è bisogno di andare molto nei dettagli, verrà spiegato solo il suo funzionamento di base e il suo uso generale.

Teoria

sistema di controllo di versione''Distribuito''

Noi abbiamo analizzato git come Sistema di Controllo di Versione, ma git è un VCS Distribuito. Distribuito è un dettaglio dell'architettura di git, che ha alcuni pro e alcuni contro. Ci sono altri "sistemi VCS famosi, come CVS e SVN, chiamati VCS Centralizzati; questi hanno bisogno di avere una connessione al server centrale, per conservare tutti i dati e per eseguire molte operazioni. Pensa al comando log: SVN ha bisogno di connettersi al server e scaricare i dati.

  • Con i VCS Distribuiti (e git è uno di questi) ciò non avviene: ogni copia del repository è una copia completa. Questo significa che le operazione sono più veloci, e che soprattutto puoi usare git sul tuo computer locale, senza avere un server.

Ovviamente anche i VCS Distribuiti hanno i loro difetti, il problema più importante che ho riscontrato è il gran numero di conflitti'. Questo perché con i VCS Centralizzati un commit è di solito rifiutato se conflitta con la copia del server. Invece con i VCS distrubuiti, chiunque può eseguire un commit nel suo repo, e conflitta solo quando viene pushato (il termine "push" verrà spiegato in seguito).

Il modello di immagazzinamento di git

Ogni oggetto all'interno di un repository git è identificato da una stringa univoca. Questa è chiamata hash. Normalmente è una somma SHA1 di alcune proprietà di cui parleremo più tardi.

Un oggetto git può essere un blob, un tree, commit o tag. Guardiamoli uno alla volta:

  • Un blob è un oggetto git su cui sono conservati i dati. Questo è generalmente un file su disco.

  • Un tree è come una cartella, fa referenza ad altri tree e/o blob. Immaginalo come una cartella con file e sottocartelle al suo interno.

  • Un commit è una referenza ad un singolo tree, e contiene anche altre meta-informazioni, come il timestamp, l'autore (nome ed email) che ha apportato le modifiche e un puntatore al commit precedente. Generalmente, quando si usa git, si fa riferimento solo ai commit.

  • Un tag è solo un modo per segnare un commit come se fosse in un certo modo speciale. Generalmente, i tag vengono usati per segnare commit con i numeri di versione, release e così via.

Se pensiamo al modello di immagazzinamento di git, distinguiamo una "area di lavoro", un "index" e un "repository":

  • L' area di lavoro è composta dai file presenti nella nostra cartella git

  • L' index e repository, invece, sono contenuti all'interno di ./.git/ -- qui è dove tutti i repository git risiedono, ed è sufficiente per ricreare il contenuto delle cartelle. Andando oltre, possiamo dire che l' index è come una temporanea area di sosta, dove tu puoi aggiungere i file prima di eseguire il commit. Una volta che il commit è stato eseguito, il contenuto andrà all'interno del repository, e l'azione compiuta verrà conservata nella sua cronologia, se tu non esegui il commit, puoi rimuovere i file dall'index senza lasciare traccia nella cronologia del repository.

Pratica

Creare un repository

Per la parte pratica, ho voluto usare un progetto reale, anzichè creare qualche repository. Ho scelto di usare "GNU Hello", scaricalo da http://ftp.gnu.org/gnu/hello/hello-2.6.tar.gz. Noi creeremo un repository da questo codice sorgente.

Scarichiamo il tarball:

$ wget http://ftp.gnu.org/gnu/hello/hello-2.6.tar.gz

Una volta fatto, spacchettiamolo:

$ tar zxvf hello-2.6.tar.gz

Questo comando creerà la cartella hello-2.6/. Adessim entriamo nella cartella ed iniziamo a giocare con git :) Prima di tutto, abbiamo bisogno di configurare il nostro username e la nostra e-mail. Queste informazioni verranno usate nei nostri commit, e saranno visibili nella cronologia del repository. Per fare ciò, usiamo git config. In particolare, visto che siamo dei principianti, vogliamo settare username ed e-mail in modo globale. Quindi lanciamo i comandi:

$ git config --global user.name "Debian Woman Attendant"
$ git config --global user.email "attendant@debian.org"

Naturalmente usa i tuoi dati :)

L'opzione --global fa in modo che il cambiamento sia globale, ad esempio per ogni repository git sul tuo computer lui scrivere le informazioni in ~/.gitconfig. Controlla questo file, dopo che avrai eseguito questi due comandi. Vedrai le informazioni che hai fornito.

L'username e l'e-mail possono anche essere cambiate in base al repository: in questo caso, puoi farlo dopo aver creato il repository, e senza l'opzione --global. Senza --global, lui inserirà le informazioni localmente in ./.git/config.

Abbiamo impostato l'username e l'e-mail. Ora, abbiamo bisogno di creare il repository git. Quindi abbiamo una cartella hello-2.6/: entriamoci ed lanciamo:

$ git init

Il risultato sarà qualcosa di simile:

Initialized empty Git repository in /tmp/dw/hello-2.6/.git/

git init semplicemente crea una cartella .git/, come alcuni valori di default. Per vedere lo stato di un repository, lancia:

$ git status

Ti mostrarà i file monitorati e non, e lo stato dell'index. In più, ti mostrerà in qualche branch sei (spiegerò i branch più tardi).

Indexing

Non abbiamo ancora nulla nel repository. Quindi aggiungiamo il codice sorgente:

$ git add .

Il "." è una sintassi dei sistemi Unix-like -- significa "cartella corrente". Quindi in questo modo aggiungiamo tutto il contenuto. Ora, controlla git status di nuovo. Vedrai che qualcosa è cambiato. Quello che vedi ora è lo stato di index.

Noi possiamo ancora rimuovere file o cartelle dall'index, senza lasciare tracce nella cronologia. Facciamolo! rimuoviamo il file We could still remove things from the index, without leaving traces in the repository history. Let's do it! Let's remove AUTHORS dall'index e rimettiamo nello stato di "non tracciato"

$ git rm --cached AUTHORS

Ora dai di nuovo uno sguardo a git status. Vedrai Changes to be committed(cambiamenti che devono essere committati) (l'index) e Untracked files (file non tracciati).

Committing

Ora vogliamo committarei file nell'index: questo creerà un commit, con un hash, e verrà conservato nella cronologia del repository. Lanciamo:

$ git commit

Questo comando aprirà il tuo $EDITOR (il mio è nano, controlla il tuo), dove tu dovrai scrivere un messaggio di commit. Se tu non ne scrivi uno, il commit verrà annullato (si, tu devi inserire un messaggio di commit)

Chiamiamolo "Commit iniziale". Ora, lancia di nuovo git status . I file dall'index sono spariti! Sono stati committati all'interno del repository, e il log è stato conservato.

Puoi vedere i log con:

$ git log

Ti verrà mostrato il committer(l'autore del commit, con le informazioni inserite prima), il timestamp, e l'hash del commit.

Puoi anche vedere l'ultimo commit con:

$ git show

Aprirà automaticamente $PAGER e mostrerà il contenuto del tuo ultimo commit. git show accetta anche un hash come argomento. Il mio commit ha hash: 11aab8486d20490b16b1b7d847e1cb1e4f7aa2fe . Che è differente dal uno dei tuoi. Non è necessario scrivere l'hash completo --normalmente bastano i primi 7,8 caratteri. Quindi possiamo lanciare:

$ git show 11aab848

git supporta anche un numero di nomi simbolici, ma non verranno spiegati ora in quanto credo non siano argomenti "di base" da poter essere spiegati in questa sessione (Sto parlando di HEAD, HEAD^, HEAD~2 e così via)

Quindi, abbiamo rimosso AUTHORS dal nostro repository... poveracci! nessun merito al loro lavoro! Correggiamo No credit for their work! possiamo correggere questo problema:

$ git add AUTHORS
$ git commit -m 'Also add AUTHORS'

-m è una scorciatoia per il messagio -- evita così di aprire $EDITOR

Ora, abbiamo bisogno di moficare alcuni file, guarda le differenze, e commitale. Prima pretendiamo che abbiamo scritto un pezzo di codice.

Aggiungiamo il nostro nome al file AUTHORS :) E aggiungiamo anche qualcosa a "?ChangeLog". Quello che vuoi, è solo un esempio.

Ora, git status. Vedrai le prime due linee indicate con modified(modificato). Puoi vedere le differenze che hai introdotto:

$ git diff

(Opzionalmente, git diff filename mostrerà solo le differenze in quel file.)

Se sei felice con quste modifiche, committiamo!. If you're happy with the diff, let's commit it. È possibile lanciare git add uno per uno e committare git commit oppure usare soltanto:

$ git commit -a -m "Messaggio a piacere"

L'argomento -a aggiungerà tutto all'index ( ma solo i file tracciati, quelli non tracciati non saranno toccati. Vedrai:

[master 3295347] Messaggio a piacere
2 files changed, 5 insertions(+), 0 deletions(-)

master è il branch in cui siamo ora. La stringa dopo di quello è l'hash del commit --puoi usarla in molti comandi (git show <commit>, git log <commit>, etc). E dopo, vi è il messaggio di commit e le statistiche dei cambiamenti apportati (diffstats).

Branching

Cos'è un branch?

Pensa al repository git come ad un fiume. Ad un certo punto, lo sviluppo può divergere dal "flusso principale" e rimanere solo lì, oppure Think of your git repository as a river. At a certain point, development can diverge from the main flow and it can stay on its own, oppure unirsi di nuovo al fiume originale. Ora il nostro master è il fiume principale".

Creiamo un branch, chiamiamolo debian:

$ git branch debian

Per cambiare a questo nuovo branch lancia:

$ git checkout debian

Una scorciatoia per entrambi i comandi è:

$ git checkout -b debian

Ok, ora siamo nel branch debian. Per controllare se è vero, esegui git branch, senza argomenti. Ti mostrerà i branch locali, e un * anteposto ti mostrerò quello in cui sei ora.

Per tornare indietro al branch principale, esegui: git checkout master.

Ma per il momento rimarremo sul branch debian: *debian. All'interno di questo branch faremo il lavoro di pacchettizzazione.

Quindi, creiamo una cartella debian/. Se la cartella è vuota, git status non la mostrerà, è il comportamento previsto: git non tiene traccia delle cartelle vuote. Per ingannarlo a fare queto puoi aggiungere un file vuoto alla cartella. Io normalmente aggiungo un .gitignore (è un file speciale usato da git), per lasciargli tracciare una cartella vuota. Quindi eseguiamo questo:

$ mkdir debian
$ touch debian/.gitignore

Ora git status mostrerà la non-tracciata debian/. Aggiungila e committala.

Ora torniamo al branch master

$ git checkout master

Ora vogliamo far divergere questi due branch, per simulare un branch reale: cambia tutti i file che vuoi, e committa i cambiamenti.

Puoi usare un'interfaccia grafica ( come ad esempio gitg o gitk), o qualcosa da linea di comando (git show-branch) Per vedere come i due branch sono divergenti. Visto che le gui sono facili da usare, useremo la riga di comando :D)

$ git show-branch

Vedrai che i due branch hanno un commit inziale in comune, ma apparte questo hanno commit differenti. Quindi uniamo i cambiamenti di "debian" in "master"

$ git merge debian

Vedrai qualcosa come:

Merge made by recursive.
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 debian/.gitignore

E ora ci saranno dei "conflitti". Se in debian abbiamo cambiato uno dei file cambiati prima del merge, questi potrebbero andare in conflitto. Sarebbe utile lanciare git mergetool dopo il merge, per risolvere i conflitti. Userà uno dei possibili programmi per gestire i conflitti. Non voglio entrare nei dettagli --in ogni caso è sempre meglio risolvere i conflitti manualmente.

Abbiamo unito debian in master. Ora vediamo i log, dovresti vedere qualcosa come:

commit cdfd20167aa05f74f4785ef7aa03355d51add5b3
Merge: 7e9ff3a 2ba81df
Author: David Paleino <dapal@debian.org>
Date:   Thu Nov 25 23:45:28 2010 +0100

    Merge branch 'debian'

commit 7e9ff3a18dc114b4ce1e1a96f1dd3ecd696f064d
Author: David Paleino <dapal@debian.org>
Date:   Thu Nov 25 23:43:49 2010 +0100

    New author

commit 2ba81dfaeb919e6a0c634be54fe363b11487d65a
Author: David Paleino <dapal@debian.org>
Date:   Thu Nov 25 23:42:42 2010 +0100

    add debian/

commit 3295347b1dbd7b5925dca7fcc6858af51a710ada
Author: David Paleino <dapal@debian.org>
Date:   Thu Nov 25 23:32:55 2010 +0100

    Some message

commit f6aa148a5ce1331de6d17e770a8efbb98ad32344
Author: David Paleino <dapal@debian.org>
Date:   Thu Nov 25 23:11:57 2010 +0100

    Also add AUTHORS

commit 11aab8486d20490b16b1b7d847e1cb1e4f7aa2fe
Author: David Paleino <dapal@debian.org>
Date:   Thu Nov 25 23:03:42 2010 +0100

    Initial commit

Ripristino

L'ultima cosa che voglio spiegare per quanto riguarda la parte della guida in locale è git revert.

Suppomiamo che io trovi qualcosa che non mi piace nel mio git log. Per esempio diciamo che è il (mio) commit 2ba81dfaeb919e6a0c634be54fe363b11487d65a , quello con cui ho aggiunto la cartella debian/ directory. Ricordati che gli hash sono diffenti per ciascuna persona, quindi guarda i log per vedere il tuo.

Dunque, non mi piace. Cosa dovrei fare ora? Posso usare il comando git revert.

Questo comando prende semplicemente il cambiamento (diff) da un commit, e lo applica al contrario, e lascia i conflitti, se ce ne sono, proviamolo:

$ git revert 2ba81dfaeb919e6a0c634be54fe363b11487d65a

$EDITOR (nano, vim, ecc) si apre di nuovo. C'è un messaggio There is a default commit message; you can leave it as-is, or (better) explain why you're reverting the change. For the sake of simplicity, let's leave the default. Save the message, and quit the editor.

You'll see:

Finished one revert.
[master 37ce99f] Revert "add debian/"
0 files changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 debian/.gitignore

This means: a revert is a commit too. With a Committer, an Author, a Timestamp, and a Hash. Ideally, you can revert a revert. (you shouldn't do it :) )

NOTE: Reverting a merge is not that easy. You should also specify the mainline parent. Read about the -m switch of git revert. It also has some nasty (IMHO) side-effects, so don't merge if you're not absolutely sure.