Si pu`o usare git nel modo difficile per questo, ma questa sezione presume l’uso del comndo di utilit`a git trac, che semplifica molte delle azioni pi`u comuni nella collaborazione su Sage. Sage stesso ha gi`a disponibili al suo interno un pi`u limitato set di azioni con cui lavorare (vedi tutorials), ma la strada raccomandata `e utilizzare questa sezione del manuale per incominciare.
La maggior parte dei comandi nella sezione seguente non funzioner`a se non si dispone di un account su Trac. Se voui contribuire a Sage, `e una buona idea ottenere un account subito (vedi Ottenere un account).
Git `e un progetto separato da Trac, ed i due non sanno come parlarsi l’un l’altro. Per semplificare lo sviluppo, abbiomo uno speciale comando git trac per la suite Git. Nota che ci`o `e realmente solo per semplificare l’interazione con la nostra gestione delle richieste Trac: `e possibile effettuare tutto lo sviluppo con solo Git ed un browser web. Vedi Git the Hard Way se preferisci invece fare tutto a mano:
[user@localhost]$ git clone https://github.com/sagemath/git-trac-command.git
Cloning into 'git-trac-command'...
[...]
Checking connectivity... done.
[user@localhost]$ source git-trac-command/enable.sh
Prepending the git-trac command to your search PATH
Questo crea una directory git-trac-command.
Mettere l`i il codice dello script enable.sh `e solo un modo spiccio di abilitarlo temporaneamente. Per una installazione pi`u permanente sul tuo sistema, successivamente, accertati di mettere il comando git-trac nel tuo PATH. Se nel tuo PATH c’`e gi`a ~/bin, puoi farlo con un link simbolico:
[user@localhost]$ echo $PATH
/home/user/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin
[user@localhost]$ cd git-trac-command
[user@localhost git-trac-command]$ ln -s `pwd`/git-trac ~/bin/
Vedi git-trac README per maggiori dettagli.
Note
Devi predisporre entrambi i meccanismi di autenticazione per poter mandare le tue modifiche con “git trac”. Per un accesso in sola lettura non `e necessario alcun meccanismo di autenticazione. Per far funzionare “git trac”, prima va nela directory di Sage e imposta in git trac il tuo account Trac:
[user@localhost sage]$ git trac config --user USERNAME --pass 'PASSWORD'
Trac xmlrpc URL:
http://trac.sagemath.org/xmlrpc (anonymous)
http://trac.sagemath.org/login/xmlrpc (authenticated)
realm sage.math.washington.edu
Username: USERNAME
Password: PASSWORD
Retrieving SSH keys...
1024 ab:1b:7c:c9:9b:48:fe:dd:59:56:1e:9d:a4:a6:51:9d My SSH Key
dove devi sostituire USERNAME con il tuo username per Trac e PASSWORD con la tua password per Trac. Se non hai un account Trac, usa git trac config senza argomenti. Gli apici singoli in 'PASSWORD' effettuano l’escape di eventuali caratteri speciali presenti nella tua password. La password `e registrata in chiaro nel file .git/config, per cui accertati che altri utenti del tuo sistema non abbiano i permessi di lettura di tale file, ad esempio eseguendo chmod 0600 .git/config qualora la tua home directory non fosse gi`a privata.
Se non viene elencata alcuna chiave SSH allora non hai ancora caricato sul server Trac la tua chiave pubblica. Dovresti farlo adesso seguendo le istruzioni in Collegare manualmente la tua chiave pubblica al tuo account Trac se vuoi inviare delle mofiche al codice sorgente.
Note
Il comando git-trac config aggiunger`a automaticamente un server Trac al tuo elenco di repository git remoti, qualora necessario.
Se hai seguito le istruzioni suddette allora avrai 2 repository remoti impostati:
[user@localhost sage]$ git remote -v
origin git://github.com/sagemath/sage.git (fetch)
origin git://github.com/sagemath/sage.git (push)
trac git://trac.sagemath.org/sage.git (fetch)
trac git@trac.sagemath.org:sage.git (push)
La parte dell’URL di push git@... significa che l’accesso in scritto `e protetto con chiavi SSH, che devi avere impostato come in Collegare manualmente la tua chiave pubblica al tuo account Trac. L’accesso in sola lettura viene eseguito attraverso l’URL di fetch e non richiede SSH.
Infine, se non vuoi utilizzare del tutto il comando git trac allora devi impostare i repository remoti a mano come mostrato nella sezione Il server Trac.
Ora iniziamo ad aggiungere codice a Sage !
Supponiamo che hai scritto un algoritmo per calcolare l’ultimo numero primo gemello, e vuoi aggiungerlo a Sage. Apriresti innanzitutto un ticket Sage per questo:
[user@localhost sage]$ git trac create 'Last Twin Prime'
Remote branch: u/user/last_twin_prime
Newly-created ticket number: 12345
Ticket URL: http://trac.sagemath.org/12345
Local branch: t/12345/last_twin_prime
Questo creer`a un nuovo ticket Trac intitolato “Ultimo numero primo gemello” con un ramo remoto u/user/last_twin_prime attaccato ad esso. Il nome del ramo remoto `e derivato automaticamente dal titolo del ticket; se non ti piace puoi usare l’opzione -b per specificarlo esplicitamente. Vedi git trac create -h per dettagli. Questo nuovo ramo `e automaticamente impostato per te con il nome di ramo locale t/12345/last_twin_prime dove 12345 `e il numero del ticket.
Note
Solo alcuni campi di Trac sono riempiti automaticamente. Vedi I campi dei ticket per vedere quali campi di un ticket Trac sono disponibili e come usarli.
In alternativa puoi usare l’interfaccia web del server di sviluppo Trac di Sage per aprire un nuovo ticket. Semplicimente fai login e poi fai click su “Crea ticket”.
Invece magari qualcuno ha gi`a aperto un ticket. Allora, per ottenere un ramo locale adatto all’esecuzione delle modifiche che vuoi apportare, dovrai eseguire:
[user@localhost sage]$ git trac checkout 12345
Loading ticket #12345...
Checking out Trac #13744 remote branch u/user/last_twin_prime -> local branch t/12345/last_twin_prime...
Il comando git trac checkout scarica in locale un ramo gi`a esistente (come specificato nel campo “Branch:” (ramo) del ticket Trac) o ne crea uno nuovo se non ce n’`e ancora nessuno. Come con il comando “create”, se vuoi puoi specificare il nome del branch remoto esplicitamente utilizzando l’opzione -b.
I ticket Trac che sono terminati o su cui si sta lavorando possono avere attaccato ad essi un ramo Git: il campo “Branch:” del ticket (vedi I campi dei ticket) indica il ramo di git che contiene il codice. In genere il nome del ramo `e della forma “u/user/description”, dove user `e il nome dell’utente che ha generato il ramo e description `e qualche breve descrizione in forma libera (e pu`o includere ulteriori barre “/” ma non degli spazi bianchi). Il nostro server Git implementa le seguenti restrizioni d’accesso per i nomi remoti di ramo:
* solo lo svilppatore che ha come account "user" pu\`o
creare dei rami che iniziano con u/user.
In base al tuo stile di collaborazione, puoi usare l’uno o l’altro. Il comando git trac di default imposta il primo.
Come convenzione il comando git trac usa nomi locali di ramo della forma t/12345/description, dove il numero `e il numero del ticket di Trac. Lo script usa questo numero per risalire al ticket dal nome del ramo locale. Puoi rinominare i rami locali se vuoi, ma se non contengono il numero di ticket allora dovrai specificarlo manualmente quando effettui l’upload delle modifiche.
Una volta che hai fatto il check-out di un ticket, modifica i file appropriati e fa il commit dei tuoi cambiamenti al ramo come descritto in Modificare il codice sorgente e I commit (snapshots).
Ad un certo momento potresti voler condividere le tue modifiche con il resto di noi: magari sono pronte per la revisione, o magari stai collaborando con qualcuno e vuoi condividere le modifiche fatte “fino ad oggi”. Questo si fa facilmente con:
[user@localhost sage]$ git trac push
Pushing to Trac #12345...
Guessed remote branch: u/user/last_twin_prime
To git@trac.sagemath.org:sage.git
* [new branch] HEAD -> u/user/last_twin_prime
Changing the trac "Branch:" field...
Questo effettua l’upload delle tue modifiche in un ramo remoto del server Git di Sage). Il comando git trac segue la seguente logica per individuare il nome del ramo remoto:
Puoi fare l’upload di qualunque ramo locale ad un ticket esistente, che tu abbia o no creato tale ramo con il comando git trac. Questo funziona esattamente come nel caso in cui parti con un ticket, eccetto che devi specificare il numero di ticket (dal momento che non cisarebbe altro modo di sapere che ticket hai in mente). Cio`e:
[user@localhost sage]$ git trac push TICKETNUM
dove devi scrivere il numero di ticket trac al posto di TICKETNUM.
`E comune passare attraverso alcuni commit successivi prima di effettuare l’upload, ed anche probabilmente ti capiter`a di effettuare il push pi`u di una volta prima che le tue modifiche siano pronte per la revisione.
Una volta che sei soddisfatto delle modifiche di cui hai fatto l’upload, ne deve essere fatta la revisione da qualcun altro prima che possano essere incluse nella prossima versione di Sage. Per segnare sul tuo ticket che esso `e pronto per la revisione, devestri impostarne lo stato a needs_review sul server Trac. Inoltre imposta te stesso come autore (o aggiungiti agli altri autori) di quel ticket immettendo la seguente come prima riga:
Authors: Your Real Name
Se qualcun altro ha lavorato sul ticket, o se hai appena cambiato computer, vorrai ottenre l’ultima versione del ramo di un ticket sul tuo ramo locale. Questo si fa con:
[user@localhost sage]$ git trac pull
Tecnicamente questo effettua un merge (fusione), proprio come il comando git pull standard. Vedi Merge e rebase per maggiori informazioni).
Non appena hai lavorato su un progetto pi`u grande che copre pi`u ticket vorrai basare il tuo lavoro su rami di cui non `e ancora stato effettuato il merge in Sage. Questo `e naturale nello sviluppo collaborativo, tanto che sei incoraggiato a dividere il tuo lavoro in parti differenti a livello logico. Idealmente, ogni parte che `e utile per conto suo e di cui pu`o essere fatta la revisione indipendentemente, dovrebbe essere su un ticket per conto suo, invece di fare una enorme “patch bomb”.
A questo scopo puoi incorporare rami relativi ad altri ticket (o altri rami locali) nel tuoramo corrente. Questo si chiama effettuare un merge, e tutto quello che fa `e includere i commit dagli altri rami nel tuo ramo corrente. In particolare si fa questo quando si fa una nuova release di Sage: i ticket terminati sono fusi con la versione “master” (prototipo) di Sage ed il risultato `e la versione successiva di Sage. Git `e cos`i bravo da non effettuare la fusione dei commit 2 volte. In particolare `e possibile fondere 2 rami, di cui uno `e gi`a stato fuso con l’altro ramo. La sintassi per effettuare la fusione `e semplice:
[user@localhost sage]$ git merge other_branch
Questo crea un nuovo commit “di fusione”, unendo il tuo ramo corrente ed il ramo other_branch.
Warning
Si dovrebbe evitare di effettuare fusioni in entrambe le direzioni. Una volta che A `e stato fuso con B e B `e stato fuso con A non c’`e pi`u modo di distinguere i commit che erano stati fatti originariamente su A o su B. Nei fatti la fusione in entrambe le direzioni mescola i 2 rami e rende la revisione separata impossibile.
In pratica dovresti effettuare la fusione solo in uno di questi 2 casi:
Un caso speciale di fusione `e quando si effettua la fusione con il ramo master di Sage. Questo aggiorna il tuo ramo locale con la versione pi`u recente di Sage. La suddetta avvertenza contro le fusioni non necessarie si applica ancora, comunque. Cerca di effettuare tutto il tuo sviluppo all’interno delle versione di Sage in cui lo hai iniziato. L’unica ragione di effettuare una fusione con il ramo master `e se hai bisogno di una funzionalit`a nuova oppure se il tuo ramo `e in conflitto.
`E molto facile collaborare semplicemente eseguendo i passaggi suddetti tante volte quanto necessario. Ad esempio, Alice inizia un ticket ed aggiunge del codice iniziale:
[alice@laptop sage]$ git trac create "A and B Ticket"
... EDIT EDIT ...
[alice@laptop sage]$ git add .
[alice@laptop sage]$ git commit
[alice@laptop sage]$ git trac push
Ora il ticket Trac ha il campo “Branch:” impostato a u/alice/a_and_b_ticket. Bob fa il download del ramo e svolge dell’altro lavoro su di esso:
[bob@home sage]$ git trac checkout TICKET_NUMBER
... EDIT EDIT ...
[bob@home sage]$ git add .
[bob@home sage]$ git commit
[bob@home sage]$ git trac push
Il ticket Trac ora ha il campo “Branch:” impostato a u/bob/a_and_b_ticket, poich`e Bob non pu`o scrivere su u/alice.... Ora i 2 autori semplicemente effettuano dei pull e push per collaborare:
[alice@laptop sage]$ git trac pull
... EDIT EDIT ...
[alice@laptop sage]$ git add .
[alice@laptop sage]$ git commit
[alice@laptop sage]$ git trac push
[bob@home sage]$ git trac pull
... EDIT EDIT ...
[bob@home sage]$ git add .
[bob@home sage]$ git commit
[bob@home sage]$ git trac push
Non `e necessario che Alice e Bob si alternino, essi possono anche aggiungere ulteriori comit in cima al loro proprio ramo remoto. Fintanto che le loro modifiche non sono in conflitto (modifica contemporanea delle stesse lineee di codice), non c’`e problema.
I conflitti di fusione accadono quando vi sono delle modifiche che si sovrappongono, e sono una conseguenza inevitabile dello sviluppo distribuito. Fortunatamente il risolverli `e cosa comune e semplice con Git. Come esempio ipotetico, si consideri il seguente frammento di codice:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
return fibonacci(i-1) * fibonacci(i-2)
Questo `e chiaramente sbagliato. Due sviluppatori, Alice e Bob, decidono di correggerlo. Dapprima, in una capanna nella foresta lontano da ogni connessione Internet, Alice corregge il valore iniziale:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
if i > 1:
return fibonacci(i-1) * fibonacci(i-2)
return [0, 1][i]
e passa tali modifiche ad un nuovo commit:
[alice@laptop sage]$ git add fibonacci.py
[alice@laptop sage]$ git commit -m 'return correct seed values'
Tuttavia, non avendo una connessione Internet, non pu`o mandare immediatamente le sue modifiche al server Trac. Nel frattempo Bob cambia la moltiplicazione in una addizione dal momento che questa `e la formula ricorsiva corretta:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
return fibonacci(i-1) + fibonacci(i-2)
Ed invia immediatamente le modifiche al server:
[bob@home sage]$ git add fibonacci.py
[bob@home sage]$ git commit -m 'corrected recursion formula, must be + instead of *'
[bob@home sage]$ git trac push
Quando Alice ritorna nel mondo civile, nella sua casella diposta elettronica trova una notifica di Trac che Bob ha effettuato ulteriori modifiche al loro progetto comune. Pertanto inizia a scaricare tali modifiche nel suo ramo locale:
[alice@laptop sage]$ git trac pull
...
CONFLICT (content): Merge conflict in fibonacci.py
Automatic merge failed; fix conflicts and then commit the result.
Ora il file appare cos`i:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
<<<<<<< HEAD
if i > 1:
return fibonacci(i-1) * fibonacci(i-2)
return i
=======
return fibonacci(i-1) + fibonacci(i-2)
>>>>>>> 41675dfaedbfb89dcff0a47e520be4aa2b6c5d1b
Il conflitto `e evidenziato fra i marcatori di conflitto <<<<<<< e >>>>>>>. La prima met`a (fino al marcatore =======) `e la versione corrente di Alice, la seconda met`a `e la versione di Bob. Il numero esadecimale di 40 cifre dopo il secondo marcatore di conflitto `e l’hash SHA1 del pi`u recente genitore di entrambi.
Ora `e compito di Alice risolvere il conflitto riconciliando le modifiche, ad esempio modificando il file. Il suo risultato `e:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
if i > 1:
return fibonacci(i-1) + fibonacci(i-2)
return [0, 1][i]
E poi fare l’upload su Trac sia della sua modifica originale che del suo commit di fusione:
[alice@laptop sage]$ git add fibonacci.py
[alice@laptop sage]$ git commit -m "merged Bob's changes with mine"
Il grafo di commit risultante ora presenta un ciclo:
[alice@laptop sage]$ git log --graph --oneline
* 6316447 merged Bob's changes with mine
|\
| * 41675df corrected recursion formula, must be + instead of *
* | 14ae1d3 return correct seed values
|/
* 14afe53 initial commit
Se Bob decide di fare altro lavoro sul ticket allora dovr`a fare un pull dei cambiamenti di Alice.Tuttavia questa volta non c’`e alcun conflitto dal suo lato: Git scarica sia il commit conflittuale di Alice che la sua soluzione.
Questa sezione mostra un esempio di come effettuare una revisone utilizzando il comando sage. Per una discussione dettagliata del processo di revisione in Sage vedere La check list del revisione. Se vai a interfaccia web del server di sviluppo Trac di Sage puoi fare click sul campo “Branch:” e vedere il codice che `e stato aggiunto come combinazione di tutti i commit sul ticket. Questo `e ci`o di cui occorre fare la revisione.
Il comando git trac ti fornisce 2 opzioni che possono esserti utili (sostituire 12345 con il numero di ticket effettivo) se non vuoi utilizzare l’interfaccia web: