Differenze tra le versioni di "Git"

Da GolemWiki.
m
(Inseriti alcuni comandi frequentemente usati, ma difficili da ricordare.)
 
(13 versioni intermedie di 3 utenti non mostrate)
Riga 1: Riga 1:
== Pagina in costruzione ==
+
{{Note
 +
|type=info
 +
|text=Questa pagina è in continua evoluzione
 +
}}
  
 
Git è un [https://it.wikipedia.org/wiki/Controllo_versione_distribuito sistema di controllo versione] nato nel 2005 ad opera di Linus Torvalds con l'obiettivo principale di versionare il Kernel Linux.
 
Git è un [https://it.wikipedia.org/wiki/Controllo_versione_distribuito sistema di controllo versione] nato nel 2005 ad opera di Linus Torvalds con l'obiettivo principale di versionare il Kernel Linux.
Riga 16: Riga 19:
 
  <repository_git_attuale>/.git/config  ''# configurazione per singola cartella''
 
  <repository_git_attuale>/.git/config  ''# configurazione per singola cartella''
 
  ~/.gitconfig                          ''# configurazione base per l'utente corrente''
 
  ~/.gitconfig                          ''# configurazione base per l'utente corrente''
  /etc/gitconfig                        ''# configurazione di sistema''
+
  /etc/gitconfig                        ''# configurazione di sistema (non necessariamente presente)''
  
 
Alcune configurazioni importanti:
 
Alcune configurazioni importanti:
Riga 27: Riga 30:
  
 
= Comandi di base =
 
= Comandi di base =
asd
 
 
== init ==
 
== init ==
 
Inizializzare un repository vuoto:
 
Inizializzare un repository vuoto:
Riga 56: Riga 58:
 
L'esecuzione del comando commit senza l'aggiunta di file alla Staging Area (e quindi senza nemmeno l'opzione <code>-a</code>) non avrà alcun effetto.
 
L'esecuzione del comando commit senza l'aggiunta di file alla Staging Area (e quindi senza nemmeno l'opzione <code>-a</code>) non avrà alcun effetto.
  
 +
Se si commette un piccolo errore in una commit e si vuole modificare un file o il messaggio di commit stesso, senza però dover creare una nuova commit, può essere aggiunta l'opzione:
 
  $ git commit --amend
 
  $ git commit --amend
 +
 +
'''!! ATTENZIONE: Non''' eseguire <code>--amend</code> su una commit che è già stata inviata ad un server remoto condiviso.
  
 
== Log ==
 
== Log ==
 
  $ git log
 
  $ git log
elenca tutta la cronologia delle commit corredata di somma ''SHA1'', autore, data e ora di commit e messaggio.
+
elenca tutta la cronologia delle commit corredata di somma [https://it.wikipedia.org/wiki/Secure_Hash_Algorithm SHA-1], autore, data e ora di commit e messaggio.
  
 
È uno dei comandi col maggior numero di opzioni, dalla formattazione dell'output (più informazioni sull'autore, sulle commit firmate) al filtraggio (per autore, per data, per messaggio, etc...). Alcune delle più importanti sono:
 
È uno dei comandi col maggior numero di opzioni, dalla formattazione dell'output (più informazioni sull'autore, sulle commit firmate) al filtraggio (per autore, per data, per messaggio, etc...). Alcune delle più importanti sono:
Riga 76: Riga 81:
 
* fare un fork di un progetto già esistente
 
* fare un fork di un progetto già esistente
  
 +
== Configurare un repository remoto ==
 +
=== Server privato ===
 +
Se si ha a disposizione un server personale (VPS o domestico), questo può essere configurato come repository git remoto. Per una configurazione base, è sufficiente avere a disposizione un server SSH (quasi sicuramente già presente) e installare git (vedi sezione installazione). Eseguire quindi
 +
cd /home/utente/<cartella_git>
 +
git init --bare
 +
Si noti in questo caso l'utilità dell'opzione <code>bare</code>, che non crea una ''working directory'' su cui poter lavorare direttamente (spesso non necessaria su un server) ma solo il database dei file, risparmiando spazio di archiviazione.
 +
 +
=== Servizio online ===
 +
In alternativa ci si può affidare ad un servizio online, come [https://github.com GitHub] (il più popolare) o [https://bitbucket.org BitBucket]. Dopo il login (email o nome utente e password) si può procedere alla creazione di un nuovo repository con l'apposito pulsante. Saranno forniti quindi due URL per accedere:
 +
<nowiki>https://github.com/NOME_UTENTE/NOME_REPOSITORY</nowiki>  ''# URL https per sola lettura (download pubblico)''
 +
git@github.com:NOME_UTENTE/NOME_REPOSITORY.git  ''# Sintassi SSH anche per la scrittura (se il proprietario ci autorizza alla modifica)''
  
== Aggiungere un repository remoto ==
+
== Collegare il repo locale a quello remoto ==
 
=== Nuovo ===
 
=== Nuovo ===
git remote add
+
In entrambi i casi, dopo aver creato un repo remoto si deve comunicare a git di collegare quell'URL al repo locale.
 +
git remote add origin git@github.com:NOME_UTENTE/NOME_REPOSITORY.git  ''# Aggiungere l'URL''
 +
git push                                                              ''# Inviare il lavoro locale sul server''
 +
'''Nota:''' il nome ''origin'' (così come ''master'' per il ramo principale) è solamente una convenzione e può essere scelto a piacere.
 +
 
=== Esistente ===
 
=== Esistente ===
fork
+
Se il repo a cui collegarsi esiste già, usiamo il comando
git clone
+
git clone git@github.com:NOME_UTENTE/NOME_REPOSITORY.git
 +
 
 +
Nel log, tutti i rami figureranno come <code>origin/ramo-1</code>. Per potersi ''agganciare'' con un ramo locale:
 +
git checkout origin/ramo-1                      ''# Spostarsi sulla commit puntata da ramo-1 remoto''
 +
git checkout -b ramo-1                          ''# Creare un nuovo ramo locale su questa commit''
 +
git branch --set-upstream-to=origin/ramo-1      ''# Agganciare ramo-1 a origin/ramo-1''
 +
'''Nota:''' non è obbligatorio che il ramo locale abbia lo stesso nome del ramo remoto a cui è agganciato (ecco perché questi passaggi non sono automatici), ma fare il contrario sarebbe follia!
 +
 
 +
== Push e Pull ==
 +
A questo punto si può leggere e scrivere sui rami remoti del server origin/master, origin/ramo-1, etc. servendosi dei rami locali master, ramo-1, etc. coi quali eseguiamo l'ordinaria amministrazione del progetto.
 +
Usiamo per leggere e scrivere (rispettivamente) i comandi
 +
git pull
 +
git push
 +
 
 +
= Lavorare con git =
 +
== Lavorare in team ==
 +
[[File:Git-bad-merging.png|thumb|Una piazzola]]
 +
Quando si lavora in gruppo c'è sempre il rischio di "incrociarsi" nel pushare nuove commit, con conseguenti intrecci nella storia del progetto (amichevolmente detti "piazzole di sosta").
 +
Per evitare ciò conviene seguire una procedura standard: non so se è la migliore però finora non ha mai dato problemi.
 +
 
 +
#Effettuare le proprie modifiche, al termine verificare se altri utenti hanno effettuato aggiornamenti nel mentre utilizzando
 +
#:<code>git fetch</code>
 +
#:Se non viene stampato alcunché si può saltare al punto 6 effettuando la commit e pushando regolarmente.
 +
#Altrimenti, aggiungere i files modificati alla ''staging area'' ed "accantonarli" in una '''stash'''. È utile specificare un messaggio di stash (come fosse una commit) per individuarla più facilmente nel caso ci fossero altre stash.
 +
#: <code>git stash push -m "merging in progress"</code>
 +
#A questo punto la cartella è stata riportata all'ultima commit scaricata. Effettuare il pull per scaricare le novità
 +
#: <code>git pull</code>
 +
#Recuperare le modifiche dallo stash. Questa operazione è analoga ad un merge, ma al termine non rimarrà traccia nella storia, che proseguirà linearmente
 +
#: <code>git stash pop</code>
 +
#Se il ''merge'' dallo stash va a buon fine si può passare al punto successivo, la stash viene eliminata automaticamente. Se invece le modifiche fatte confliggono con le novità appena scaricato (ciò viene notificato da git) è necessario integrare manualmente i punti (individuabili anche con <code>git diff</code>), ed eliminare la stash manualmente (<code>git stash list</code> per individuarla, <code>git stash drop stash@{xxx}</code> per eliminarla).
 +
#Il patema è finito, si può fare la commit e pushare, sperando che nella lettura di questa lista nessuno abbia fatto altro. Altrimenti ripartire dal punto 1.
 +
#: <code>git commit -m "commit interessante"<br/>git push</code>
 +
 
 +
== Fondere più commit in uno solo ==
 +
La storia attuale. In <span style="color: blue;">blu</span> i commit che si vogliono ''squashare'' in uno solo.
 +
<span style="color: blue;">59e5834 moved files
 +
37af4b7 added README.md and LICENSE file
 +
cd37805 repository structured as an arduino library</span>
 +
<strong>ac95564</strong> added comments for UDP part
 +
 
 +
Si sceglie l'ultimo commit appena prima:
 +
git rebase --interactive <strong>ac95564</strong>
 +
 
 +
Si apre automaticamente l'editor, e si vedono i commit (in ordine ''inverso'').
 +
Sostituire <code>pick</code> (p) con <code>squash</code> (s) per fondere i commit assieme, eccetto su quello più in alto.
 +
 
 +
Quando si chiude l'editor, si apre una nuova finestra dove è possibile editare il nuovo messaggio di commit.
 +
 
 +
== Ignorare spazi bianchi ==
 +
A volte capita di trovare codice scritto con editor non degni di questo nome, che non eliminano gli spazi vuoti in fondo alle righe.
 +
Per evitare di suscitare le ire degli scellerati manutentori, ed evitare di riempire il commit con centinaia di modifiche di spazi vuoti, usare:
 +
 
 +
git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -
 +
 
 +
== Eliminare branch ==
 +
* Locale
 +
git branch -d ''branchname''
  
 +
* Remoto
 +
git push ''origin'' --delete ''branchname''
  
 
[[Category: Howto]]
 
[[Category: Howto]]

Versione attuale delle 16:26, 3 apr 2020

Golem-template-note-info.png Questa pagina è in continua evoluzione


Git è un sistema di controllo versione nato nel 2005 ad opera di Linus Torvalds con l'obiettivo principale di versionare il Kernel Linux. Questa non vuole essere una guida esaustiva, ma un prontuario per i comandi di uso più comune, con l'aggiunta di qualche consiglio. Per una trattazione completa, si rimanda alla guida ufficiale, disponibile anche in italiano.

Installazione e configurazione

Su sistemi Debian-derivati:

# apt-get install git

Su ArchLinux:

# pacman -S git

Si consiglia l'uso di ZSH per i suggerimenti nel completamento dei comandi.

Configurazione

I file di configurazione si trovano nei seguenti percorsi:

<repository_git_attuale>/.git/config   # configurazione per singola cartella
~/.gitconfig                           # configurazione base per l'utente corrente
/etc/gitconfig                         # configurazione di sistema (non necessariamente presente)

Alcune configurazioni importanti:

$ git config user.name Tizio Caio
$ git config user.email tiziocaio@example.com
$ git config user.signingkey <FOOTPRINT GPG>
$ git config core.editor nano
$ git config alias.co checkout

Aggiungendo l'opzione --global, tali impostazioni diventeranno globali per l'utente corrente e non limitate al repository dal quale viene lanciato il comando.

Comandi di base

init

Inizializzare un repository vuoto:

$ git init <sottocartella>

Se non viene specificata una sottocartella sarà inizializzato in quella attuale. Aggiungendo l'opzione --bare sarà creato un repository di tipo bare, ovvero privo della working directory, adatto per essere usato come repository remoto e non come cartella di lavoro.

Stato dei file

Con il comando

$ git status

si ottengono informazioni sui file attualmente presenti nella cartella di lavoro: se ce ne sono di nuovi (U), modificati (M), eliminati (D), etc... Darà inoltre informazioni sulla sincronizzazione tra la commit attuale e quella remota.

Aggiungere/Rimuovere files

Aggiungere un file nuovo (untracked) o modificato (rispetto all'ultima commit eseguita) nella Staging Area, ovvero pronto per la prossima commit:

$ git add <nome_file>

Rimuovere un file dall'indice dei file tracciati (risulterà quindi untracked):

$ git rm --cached <nome_file>

Omettendo --cached il file sarà anche eliminato dalla cartella (quindi definitivamente).

Commit!

Una volta aggiunti i file desiderati alla Staging Area, la prossima commit è pronta per essere "consolidata", cioè registrata nella cronologia del repository:

$ git commit

Sarà aperto l'editor di testo scelto (vedi sezione configurazione) per scrivere un breve messaggio rappresentativo della commit. Se il messaggio non è eccessivamente lungo (come spesso accade) è sufficiente accodare al comando di commit l'opzione -m "Messaggio per la commit". Un'altra scorciatoia utile può essere l'opzione -a, che aggiunge automaticamente tutti i file modificati (rispetto all'ultima commit eseguita) alla Staging Area senza dover eseguire add ogni volta. Questa opzione agisce solo su quelli modificati e non su quelli nuovi, per i quali la add è d'obbligo almeno la prima volta.

Il comando tipico di commit sarà quindi:

$ git commit -a -m "Riparato bug. Aggiunti commenti al codice."

L'esecuzione del comando commit senza l'aggiunta di file alla Staging Area (e quindi senza nemmeno l'opzione -a) non avrà alcun effetto.

Se si commette un piccolo errore in una commit e si vuole modificare un file o il messaggio di commit stesso, senza però dover creare una nuova commit, può essere aggiunta l'opzione:

$ git commit --amend

!! ATTENZIONE: Non eseguire --amend su una commit che è già stata inviata ad un server remoto condiviso.

Log

$ git log

elenca tutta la cronologia delle commit corredata di somma SHA-1, autore, data e ora di commit e messaggio.

È uno dei comandi col maggior numero di opzioni, dalla formattazione dell'output (più informazioni sull'autore, sulle commit firmate) al filtraggio (per autore, per data, per messaggio, etc...). Alcune delle più importanti sono:

  • --all: elenca anche le commit relative ad altri branches (vedi sezione relativa)
  • --oneline: elenco sintetico con solamente ID SHA-1 e messaggio di commit
  • --graph: insieme a --all realizza una rappresentazione ASCII art della ramificazione del repository

Combinando insieme le 3 opzioni sarà visualizzata in modo sintetico (oneline) ed efficace (graph) tutta la cronologia del repo. Può essere utile definire un alias per questo comando (vedi sezione configurazione), ad esempio:

$ git config alias.megalog "log --all --oneline --graph"

Git online

Utilizzare un server git (repository remoto) può servire per:

  • avere un backup del proprio progetto
  • condividere il proprio progetto con altri
  • lavorare in team sul progetto
  • fare un fork di un progetto già esistente

Configurare un repository remoto

Server privato

Se si ha a disposizione un server personale (VPS o domestico), questo può essere configurato come repository git remoto. Per una configurazione base, è sufficiente avere a disposizione un server SSH (quasi sicuramente già presente) e installare git (vedi sezione installazione). Eseguire quindi

cd /home/utente/<cartella_git>
git init --bare

Si noti in questo caso l'utilità dell'opzione bare, che non crea una working directory su cui poter lavorare direttamente (spesso non necessaria su un server) ma solo il database dei file, risparmiando spazio di archiviazione.

Servizio online

In alternativa ci si può affidare ad un servizio online, come GitHub (il più popolare) o BitBucket. Dopo il login (email o nome utente e password) si può procedere alla creazione di un nuovo repository con l'apposito pulsante. Saranno forniti quindi due URL per accedere:

https://github.com/NOME_UTENTE/NOME_REPOSITORY  # URL https per sola lettura (download pubblico)
git@github.com:NOME_UTENTE/NOME_REPOSITORY.git  # Sintassi SSH anche per la scrittura (se il proprietario ci autorizza alla modifica)

Collegare il repo locale a quello remoto

Nuovo

In entrambi i casi, dopo aver creato un repo remoto si deve comunicare a git di collegare quell'URL al repo locale.

git remote add origin git@github.com:NOME_UTENTE/NOME_REPOSITORY.git  # Aggiungere l'URL
git push                                                              # Inviare il lavoro locale sul server

Nota: il nome origin (così come master per il ramo principale) è solamente una convenzione e può essere scelto a piacere.

Esistente

Se il repo a cui collegarsi esiste già, usiamo il comando

git clone git@github.com:NOME_UTENTE/NOME_REPOSITORY.git

Nel log, tutti i rami figureranno come origin/ramo-1. Per potersi agganciare con un ramo locale:

git checkout origin/ramo-1                       # Spostarsi sulla commit puntata da ramo-1 remoto
git checkout -b ramo-1                           # Creare un nuovo ramo locale su questa commit
git branch --set-upstream-to=origin/ramo-1       # Agganciare ramo-1 a origin/ramo-1

Nota: non è obbligatorio che il ramo locale abbia lo stesso nome del ramo remoto a cui è agganciato (ecco perché questi passaggi non sono automatici), ma fare il contrario sarebbe follia!

Push e Pull

A questo punto si può leggere e scrivere sui rami remoti del server origin/master, origin/ramo-1, etc. servendosi dei rami locali master, ramo-1, etc. coi quali eseguiamo l'ordinaria amministrazione del progetto. Usiamo per leggere e scrivere (rispettivamente) i comandi

git pull
git push

Lavorare con git

Lavorare in team

Una piazzola

Quando si lavora in gruppo c'è sempre il rischio di "incrociarsi" nel pushare nuove commit, con conseguenti intrecci nella storia del progetto (amichevolmente detti "piazzole di sosta"). Per evitare ciò conviene seguire una procedura standard: non so se è la migliore però finora non ha mai dato problemi.

  1. Effettuare le proprie modifiche, al termine verificare se altri utenti hanno effettuato aggiornamenti nel mentre utilizzando
    git fetch
    Se non viene stampato alcunché si può saltare al punto 6 effettuando la commit e pushando regolarmente.
  2. Altrimenti, aggiungere i files modificati alla staging area ed "accantonarli" in una stash. È utile specificare un messaggio di stash (come fosse una commit) per individuarla più facilmente nel caso ci fossero altre stash.
    git stash push -m "merging in progress"
  3. A questo punto la cartella è stata riportata all'ultima commit scaricata. Effettuare il pull per scaricare le novità
    git pull
  4. Recuperare le modifiche dallo stash. Questa operazione è analoga ad un merge, ma al termine non rimarrà traccia nella storia, che proseguirà linearmente
    git stash pop
  5. Se il merge dallo stash va a buon fine si può passare al punto successivo, la stash viene eliminata automaticamente. Se invece le modifiche fatte confliggono con le novità appena scaricato (ciò viene notificato da git) è necessario integrare manualmente i punti (individuabili anche con git diff), ed eliminare la stash manualmente (git stash list per individuarla, git stash drop stash@{xxx} per eliminarla).
  6. Il patema è finito, si può fare la commit e pushare, sperando che nella lettura di questa lista nessuno abbia fatto altro. Altrimenti ripartire dal punto 1.
    git commit -m "commit interessante"
    git push

Fondere più commit in uno solo

La storia attuale. In blu i commit che si vogliono squashare in uno solo.

59e5834 moved files
37af4b7 added README.md and LICENSE file
cd37805 repository structured as an arduino library
ac95564 added comments for UDP part

Si sceglie l'ultimo commit appena prima:

git rebase --interactive ac95564

Si apre automaticamente l'editor, e si vedono i commit (in ordine inverso). Sostituire pick (p) con squash (s) per fondere i commit assieme, eccetto su quello più in alto.

Quando si chiude l'editor, si apre una nuova finestra dove è possibile editare il nuovo messaggio di commit.

Ignorare spazi bianchi

A volte capita di trovare codice scritto con editor non degni di questo nome, che non eliminano gli spazi vuoti in fondo alle righe. Per evitare di suscitare le ire degli scellerati manutentori, ed evitare di riempire il commit con centinaia di modifiche di spazi vuoti, usare:

git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -

Eliminare branch

  • Locale
git branch -d branchname
  • Remoto
git push origin --delete branchname