Subversion in Azione

It's time to move from the abstract to the concrete. In this section, we'll show real examples of Subversion being used.

È il momento di passare dall'astratto al concreto. In questa sezione, saranno mostrati esempi di uso reale di Subversion.

Copie di lavoro

You've already read about working copies; now we'll demonstrate how the Subversion client creates and uses them.

Si è già letto a proposito delle copie di lavoro; adesso verrà mostrato come queste vengano create ed utilizzate dal client Subversion.

A Subversion working copy is an ordinary directory tree on your local system, containing a collection of files. You can edit these files however you wish, and if they're source code files, you can compile your program from them in the usual way. Your working copy is your own private work area: Subversion will never incorporate other people's changes, nor make your own changes available to others, until you explicitly tell it to do so. You can even have multiple working copies of the same project.

Una copia di lavoro di Subversion è un normale albero di directory sul proprio sistema locale, contenente un certo insieme di file. È possibile modificare questi file come si preferisce, e, se si tratta di file di codice sorgente, si può compilare il proprio programma esattamente nella maniera usuale. La copia di lavoro è la propria area personale di lavoro: Subversion non incorporerà mai le modifiche introdotte da altri, né renderà le proprie modifiche disponibili ad altri, fino a quando non verrà esplicitamente chiesto di farlo. È possibile perfino avere più di una copia di lavoro dello stesso progetto.

After you've made some changes to the files in your working copy and verified that they work properly, Subversion provides you with commands to publish your changes to the other people working with you on your project (by writing to the repository). If other people publish their own changes, Subversion provides you with commands to merge those changes into your working directory (by reading from the repository).

Dopo aver apportato le modifiche desiderate ai file nella propria copia di lavoro ed aver verificato che funzionino correttamente, Subversion mette a disposizione dei comandi per «pubblicare» le proprie modifiche verso le altre persone che lavorano sullo stesso progetto (scrivendo nel repository). Quando altre persone pubblicano le loro modifiche, Subversion permette di importarle nella propria directory di lavoro (leggendole dal repository).

A working copy also contains some extra files, created and maintained by Subversion, to help it carry out these commands. In particular, each directory in your working copy contains a subdirectory named .svn, also known as the working copy administrative directory. The files in each administrative directory help Subversion recognize which files contain unpublished changes, and which files are out-of-date with respect to others' work.

Una copia di lavoro contiene anche dei file aggiuntivi, creati ed aggiornati da Subversion, come supporto all'esecuzione dei comandi di cui sopra. In particolare, ogni directory nella propria copia di lavoro contiene una sottodirectory chiamata .svn, altrimenti nota come directory amministrativa della copia di lavoro. I file presenti in ciascuna delle directory amministrative aiutano Subversion a tenere traccia di quali file contengono modifiche non pubblicate e quali file non sono aggiornati rispetto al lavoro svolto da altri.

A typical Subversion repository often holds the files (or source code) for several projects; usually, each project is a subdirectory in the repository's filesystem tree. In this arrangement, a user's working copy will usually correspond to a particular subtree of the repository.

Un tipico repository di Subversion spesso contiene i file (o codice sorgente) di diversi progetti; di solito, ogni progetto è contenuto in una sottodirectory nell'albero del filesystem del repository. Seguendo questa disposizione, la copia di lavoro di un utente corrisponderà ad uno specifico sottoalbero del repository.

For example, suppose you have a repository that contains two software projects, paint and calc. Each project lives in its own top-level subdirectory, as shown in Figura 2.6, «Il filesystem del repository».

Ad esempio, supponiamo di avere un repository che contenga due progetti software, paint e calc. Ciascun progetto vive nella sua personale sottodirectory al livello più alto dell'albero del filesystem, come mostrato in Figura 2.6, «Il filesystem del repository».

Figura 2.6. Il filesystem del repository

Il filesystem del repository

To get a working copy, you must check out some subtree of the repository. (The term check out may sound like it has something to do with locking or reserving resources, but it doesn't; it simply creates a private copy of the project for you.) For example, if you check out /calc, you will get a working copy like this:

Per ottenere una copia di lavoro, si deve anzitutto eseguire il check out di un qualche sottoalbero del repository. (Il termine «check out» potrebbe erroneamente far pensare ad una azione di blocco o riserva delle risorse ma, in realtà, crea semplicemente all'utente una copia di lavoro del progetto.) Per esempio, se si effettua il check out di /calc, si otterrà una copia di lavoro con questa struttura:

$ svn checkout http://svn.example.com/repos/calc
A    calc/Makefile
A    calc/integer.c
A    calc/button.c
Checked out revision 56.

$ ls -A calc
Makefile  integer.c  button.c  .svn/

The list of letter A's indicates that Subversion is adding a number of items to your working copy. You now have a personal copy of the repository's /calc directory, with one additional entry—.svn—which holds the extra information needed by Subversion, as mentioned earlier.

La lista di A indica che Subversion stia aggiungendo un certo numero di elementi alla propria copia locale. Adesso quindi si ha una copia personale della directory/calc del repository, con un elemento aggiuntivo —.svn—che contiene tutte quelle extra informazioni menzionate in precedenza.

Suppose you make changes to button.c. Since the .svn directory remembers the file's modification date and original contents, Subversion can tell that you've changed the file. However, Subversion does not make your changes public until you explicitly tell it to. The act of publishing your changes is more commonly known as committing (or checking in) changes to the repository.

Supponiamo di aver apportato modiche a button.c. Dato che la directory .svn ricorda le date delle modifiche ai file ed i contenuti originali, Subversion può notificare che i file siano stati cambiati. Ad ogni modo, Subversion non rende pubblici i propri cambiamenti fino a quando non verrà esplicitamente richiesto. L'atto di pubblicazione dei propri cambiamenti è comunemente conosciuta comecommit (o check in) delle modifiche al repository.

To publish your changes to others, you can use Subversion's commit command:

Per pubblicare le proprie modifiche agli altri è possibile usare il comando di Subversion commit:

$ svn commit button.c
Sending        button.c
Transmitting file data .
Committed revision 57.

Now your changes to button.c have been committed to the repository; if another user checks out a working copy of /calc, they will see your changes in the latest version of the file.

Adesso le modifiche a button.c sono state sottomesse al repository; se un altro utente effettua il check out di una copia di lavoro di /calc, vedrà i propri cambiamenti nell'ultima versione del file.

Suppose you have a collaborator, Sally, who checked out a working copy of /calc at the same time you did. When you commit your change to button.c, Sally's working copy is left unchanged; Subversion only modifies working copies at the user's request.

Supponiamo di avere un altro collaboratore, Sally, che ha effettuato il check out della copia di lavoro di /calc nello stesso momento in cui è stata effettuata la nostra. Quando verranno sottomesse le modifiche al filebutton.c, la copia di lavoro di Sally rimarrà inalterata; Subversion infatti modifica le copie solamente alla richiesta dell'utente.

To bring her project up to date, Sally can ask Subversion to update her working copy, by using the Subversion update command. This will incorporate your changes into her working copy, as well as any others that have been committed since she checked it out.

Per attualizzare il proprio progetto, Sally può chiedere a Subversion di aggiornare la sua copia di lavoro, usando il comando di Subversion update. Questo incorporerà le nostre modifiche nella sua copia di lavoro, così come ogni altro cambiamento che è stato sottomesso da quando lei ha effettuato il check out.

$ pwd
/home/sally/calc

$ ls -A
.svn/ Makefile integer.c button.c

$ svn update
U    button.c
Updated to revision 57.

The output from the svn update command indicates that Subversion updated the contents of button.c. Note that Sally didn't need to specify which files to update; Subversion uses the information in the .svn directory, and further information in the repository, to decide which files need to be brought up to date.

I risultati del comando svn update indicano che Subversion ha aggiornato i contenuti di button.c. Si noti che Sally non ha dovuto specificare quali file aggiornare; Subversion usa le informazioni nella directory .svn, ed informazioni aggiuntive nel repository, per decidere quali file hanno bisogno di essere attualizzati.

Revisioni

An svn commit operation can publish changes to any number of files and directories as a single atomic transaction. In your working copy, you can change files' contents, create, delete, rename and copy files and directories, and then commit the complete set of changes as a unit.

Un comando svn commit può pubblicare i cambiamenti.

In the repository, each commit is treated as an atomic transaction: either all the commit's changes take place, or none of them take place. Subversion tries to retain this atomicity in the face of program crashes, system crashes, network problems, and other users' actions.

Nel repository, ogni commit viene trattata come una transazione atomica: vengono effettuate o tutte o nessuna delle modifiche. Subversion cerca di mantenere questa atomicità come precauzione verso i crash dei programmi, i crash dei sistemi, i problemi di rete ed altre azioni dell'utente.

Each time the repository accepts a commit, this creates a new state of the filesystem tree, called a revision. Each revision is assigned a unique natural number, one greater than the number of the previous revision. The initial revision of a freshly created repository is numbered zero, and consists of nothing but an empty root directory.

Ogni volta che il repository accetta una commit, questo crea un nuovo stato nell'albero del filesystem, che viene chiamato revisione. Ogni revisione è assegnata ad un unico numero naturale, di una unità maggiore rispetto alla revisione precedente. La revisione iniziale di un repository appena creato è numerata come zero, e consiste in nient'altro che una directory radice vuota.

Figura 2.7, «Il repository» illustrates a nice way to visualize the repository. Imagine an array of revision numbers, starting at 0, stretching from left to right. Each revision number has a filesystem tree hanging below it, and each tree is a snapshot of the way the repository looked after a commit.

Figura 2.7, «Il repository» illustra una tipo intuitivo di visualizzazione del repository. Si immagini un array di numeri di revisioni, che inizia da 0 ed incrementa da destra a sinistra. Ogni numero di revisione ha un albero di filesystem appeso al di sotto, e ogni albero è una «istantanea» di come appariva il repository dopo la commit.

Figura 2.7. Il repository

Il repository

It's important to note that working copies do not always correspond to any single revision in the repository; they may contain files from several different revisions. For example, suppose you check out a working copy from a repository whose most recent revision is 4:

È importante notare che le copie di lavoro non sempre corrispondano ad una singola revisione del repository; potrebbero contenere file di varie revisioni differenti. Ad esempio, supponiamo di effettuare check out di una copia di lavoro da un repository la cui revisione più recente è 4:

calc/Makefile:4
     integer.c:4
     button.c:4

At the moment, this working directory corresponds exactly to revision 4 in the repository. However, suppose you make a change to button.c, and commit that change. Assuming no other commits have taken place, your commit will create revision 5 of the repository, and your working copy will now look like this:

Al momento, questa directory di lavoro corrisponde esattamente alla revisione 4 del repository. Tuttavia, supponiamo di aver modificato button.c, ed aver sottomesso questo cambiamento. Assumendo che nessun'altra commit abbia avuto luogo, la propria commit creerà la revisione 5 del repository, e la propria copia di lavoro apparirà come segue:

calc/Makefile:4
     integer.c:4
     button.c:5

Suppose that, at this point, Sally commits a change to integer.c, creating revision 6. If you use svn update to bring your working copy up to date, then it will look like this:

Supponiamo che, a questo punto, Sally effettui la commit di una modifica a integer.c, creando la revisione 6. Se si usa svn update per attualizzare la propria copia di lavoro, questa apparirà come segue:

calc/Makefile:6
     integer.c:6
     button.c:6

Sally's change to integer.c will appear in your working copy, and your change will still be present in button.c. In this example, the text of Makefile is identical in revisions 4, 5, and 6, but Subversion will mark your working copy of Makefile with revision 6 to indicate that it is still current. So, after you do a clean update at the top of your working copy, it will generally correspond to exactly one revision in the repository.

La modifica di Sally a integer.c apparirà nella propria copia di lavoro, ed i propri cambiamenti saranno ancora presenti in button.c. In questo esempio il testo di Makefile è identico nelle revisioni 4, 5 e 6, ma Subversion marcherà la propria copia di lavoro di Makefile con la revisione 6 per indicare che è la corrente. Quindi, dopo aver fatto un aggiornamento al livello più alto della propria copia di lavoro, questa corrisponderà esattamente ad una revisione del repository.

Come le copie di lavoro sono in relazione con il repository

For each file in a working directory, Subversion records two essential pieces of information in the .svn/ administrative area:

Per ogni file nella directory di lavoro, Subversion registra due porzioni di informazione essenziali nell'area di amministrazione .svn/:

  • what revision your working file is based on (this is called the file's working revision), and

    il numero di revisione su cui è basata la copia di lavoro (detta revisione di lavoro del file), e

  • a timestamp recording when the local copy was last updated by the repository.

    una marca temporale relativa a quando la copia locale è stata aggiornata con il repository

Given this information, by talking to the repository, Subversion can tell which of the following four states a working file is in:

Date queste informazioni, comunicando con il repository, Subversion può decidere in quale dei seguenti quattro stati si trovi un file nella copia di lavoro:

Unchanged, and current, Non modificato ed aggiornato

The file is unchanged in the working directory, and no changes to that file have been committed to the repository since its working revision. An svn commit of the file will do nothing, and an svn update of the file will do nothing.

Il file non è stato modificato nella directory di lavoro e nessuna modifica alla sua revisione di lavoro è stata sottomessa al repository. Un comando svn commit del file non farà nulla, e un comando svn update del file non farà nulla.

Locally changed, and current, Localmente modificato ed aggiornato

The file has been changed in the working directory, and no changes to that file have been committed to the repository since its base revision. There are local changes that have not been committed to the repository, thus an svn commit of the file will succeed in publishing your changes, and an svn update of the file will do nothing.

Il file è stato modificato nella directory di lavoro e nessuna modifica alla sua revisione di lavoro è stata sottomessa al repository. Ci sono delle modifiche locali che devono essere salvate sul repository, quindi un svn commit del file pubblicherà con successo le modifiche, ed un svn update del file non farà nulla.

Unchanged, and out-of-date, Non modificato e scaduto

The file has not been changed in the working directory, but it has been changed in the repository. The file should eventually be updated, to make it current with the public revision. An svn commit of the file will do nothing, and an svn update of the file will fold the latest changes into your working copy.

Il file non è stato modificato nella directory di lavoro, ma ha subito dei cambiamenti nel repository. Il file dovrebbe essere aggiornato per renderlo sincronizzato con l'attuale revisione pubblica. Un svn commit del file non farà nulla, ed un svn update del file caricherà gli ultimi cambiamenti nella copia di lavoro.

Locally changed, and out-of-date, Localmente modificato e scaduto

The file has been changed both in the working directory, and in the repository. An svn commit of the file will fail with an out-of-date error. The file should be updated first; an svn update command will attempt to merge the public changes with the local changes. If Subversion can't complete the merge in a plausible way automatically, it leaves it to the user to resolve the conflict.

Il file è stato cambiato sia nella directory di lavoro, sia nel repository. Un comando svn commit del file fallirà con un errore di «out-of-date». Il file dovrebbe prima essere aggiornato; un comando svn update tenterà di incorporare le modifiche pubbliche con le modifiche locali. Se Subversion non può completare la fusione automatica in un modo coerente, lascerà all'utente il compito di risolvere il conflitto.

This may sound like a lot to keep track of, but the svn status command will show you the state of any item in your working copy. For more information on that command, see sezione chiamata «svn status».

Potrebbe sembrare eccessivo tener traccia di tutto questo, ma il comando svn status mostrerà la stato di ogni elemento nella copia di lavoro. Per altre informazioni su questo comando, si veda sezione chiamata «svn status».

Copie di lavoro con revisioni miste

As a general principle, Subversion tries to be as flexible as possible. One special kind of flexibility is the ability to have a working copy containing files and directories with a mix of different working revision numbers. Unfortunately, this flexibility tends to confuse a number of new users. If the earlier example showing mixed revisions perplexed you, here's a primer on both why the feature exists and how to make use of it.

Come principio generale, Subversion vuole essere il più flessibile possibile. Una particolare flessibilità deriva dalla possibilità di avere una copia di lavoro contenente file e directory con un insieme di differenti numeri di revisione. Sfortunatamente questa flessibilità tende a confondere alcuni utenti. Segue quindi un'introduzione sul perché esiste questa caratteristica e su come utilizzarla.

Update e commit sono azioni separate

One of the fundamental rules of Subversion is that a push action does not cause a pull, nor the other way around. Just because you're ready to submit new changes to the repository doesn't mean you're ready to receive changes from other people. And if you have new changes still in progress, then svn update should gracefully merge repository changes into your own, rather than forcing you to publish them.

Una delle regole fondamentali di Subversion è che un'azione di «invio» non causa una «ricezione», né viceversa. Il fatto che ci siano le condizioni per inviare nuove modifiche al repository non significa che si sia pronti per ricevere quelle apportate dagli altri utenti. Se si sta lavorando a delle modifiche, il comando svn update deve integrare gli eventuali cambiamenti avvenuti sul repository in quelle su cui si sta lavorando, piuttosto che forzare la pubblicazione.

The main side-effect of this rule is that it means a working copy has to do extra bookkeeping to track mixed revisions, and be tolerant of the mixture as well. It's made more complicated by the fact that directories themselves are versioned.

La conseguenza principale di questa regola è che implica che una copia di lavoro debba compiere attività supplementari per tener traccia delle diverse revisioni, oltre a tollerare le diversità stesse. Ciò inoltre è reso più complicato dal fatto che anche le directory stesse siano sotto controllo di versione.

For example, suppose you have a working copy entirely at revision 10. You edit the file foo.html and then perform an svn commit, which creates revision 15 in the repository. After the commit succeeds, many new users would expect the working copy to be entirely at revision 15, but that's not the case! Any number of changes might have happened in the repository between revisions 10 and 15. The client knows nothing of those changes in the repository, since you haven't yet run svn update, and svn commit doesn't pull down new changes. If, on the other hand, svn commit were to automatically download the newest changes, then it would be possible to set the entire working copy to revision 15—but then we'd be breaking the fundamental rule of push and pull remaining separate actions. Therefore the only safe thing the Subversion client can do is mark the one file—foo.html—as being at revision 15. The rest of the working copy remains at revision 10. Only by running svn update can the latest changes be downloaded, and the whole working copy be marked as revision 15.

Ad esempio, si suppone di avere una copia di lavoro completamente allineata alla revisione 10. Il file foo.html viene modificato e successivamente viene eseguito un svn commit il quale crea la revisione numero 15 nel repository. Visto l'esito positivo del comando di commit, molti utenti potrebbero pensare che la copia di lavoro sia interamente allineata con la revisione 15, ma non è così! Molti cambiamenti potrebbero essersi verificati nel repository tra la revisione 10 e la 15. Il client non sa nulla di questi cambiamenti in quanto non si è ancora eseguito il comando svn update, ed il comando svn commit non riceve nessun cambiamento. D'altronde, se il comando svn commit scaricasse automaticamente le nuove modifiche dal repository, allora sarebbe possibile allineare tutta la copia di lavoro alla revisione 15 — ma si verrebbe così ad infrangere la regola fondamentale che impone a invio e ricezione di essere azioni separate. Quindi l'unica cosa sicura che il client di Subversion possa fare è ricordare che il file —foo.html— sia aggiornato alla revisione 15. Il resto della copia di lavoro rimane alla revisione 10. Solo eseguendo un svn update si possono scaricare gli ultimissimi cambiamenti, e tutta la copia di lavoro sarà contrassegnata alla revisione 15.

È normale avere revisioni miste

The fact is, every time you run svn commit, your working copy ends up with some mixture of revisions. The things you just committed are marked as having larger working revisions than everything else. After several commits (with no updates in-between) your working copy will contain a whole mixture of revisions. Even if you're the only person using the repository, you will still see this phenomenon. To examine your mixture of working revisions, use the svn status --verbose command (see sezione chiamata «svn status» for more information.)

Di fatto ogni volta che si esegue il comando svn commit la copia di lavoro si viene a trovare in un insieme misto di revisioni. Gli elementi che sono appena stati inviati al repository avranno la revisione di lavoro più alta di ogni altro. Dopo diversi commit (senza operazioni di aggiornamento intermedie) la copia di lavoro conterrà una vasta combinazione di revisioni. Anche se una sola persona stesse usando il repository, si continuerebbe a verificare questo fenomeno. Per esaminare la miscela delle revisioni di lavoro, si può usare il comando svn status --verbose (per maggiori informazioni vedere sezione chiamata «svn status»).

Often, new users are completely unaware that their working copy contains mixed revisions. This can be confusing, because many client commands are sensitive to the working revision of the item they're examining. For example, the svn log command is used to display the history of changes to a file or directory (see sezione chiamata «svn log»). When the user invokes this command on a working copy object, they expect to see the entire history of the object. But if the object's working revision is quite old (often because svn update hasn't been run in a long time), then the history of the older version of the object is shown.

Spesso i nuovi utenti ignorano completamente che la loro copia di lavoro contenga diverse revisioni. Ciò può generare confusione, perché molti comandi sono sensibili alla revisione di lavoro degli oggetti che devono esaminare. Per esempio, il comando svn log viene utilizzato per mostrare la storia dei cambiamenti di un file o una directory (vedere sezione chiamata «svn log»). Quando un utente invoca questo comando sulla copia di lavoro di un oggetto, si aspetta di vedere l'intera storia dell'oggetto stesso. In realtà se la revisione di lavoro è piuttosto vecchia (solitamente perché non si è usato il comando svn update da molto tempo), allora viene mostrata la storia della precedente versione dell'oggetto.

Le revisioni miste sono utili

If your project is sufficiently complex, you'll discover that it's sometimes nice to forcibly backdate portions of your working copy to an earlier revision; you'll learn how to do that in Chapter 3. Perhaps you'd like to test an earlier version of a sub-module contained in a subdirectory, or perhaps you'd like to figure out when a bug first came into existence in a specific file. This is the time machine aspect of a version control system — the feature which allows you to move any portion of your working copy forward and backward in history.

Se il progetto è piuttosto complesso, a volte è meglio forzare alcune porzioni della copia di lavoro a «retrocedere» a versioni precedenti; nel Capitolo 3 si potrà vedere come fare. Si potrebbe voler testare una versione precedente di qualche componente contenuta in una sotto directory; oppure si vorrebbe capire quando un difetto è comparso per la prima volta in un certo file. Questo è l'aspetto di un sistema di controllo delle versioni che lo caratterizza come una «macchina del tempo» — la caratteristica che permette di muovere ogni porzione della copia di lavoro avanti e indietro nella storia.

Le revisioni miste hanno dei limiti

However you make use of mixed revisions in your working copy, there are limitations to this flexibility.

Qualunque uso si faccia delle revisioni miste nella copia di lavoro, ci sono sempre delle limitazioni a questa flessibilità.

First, you cannot commit the deletion of a file or directory which isn't fully up-to-date. If a newer version of the item exists in the repository, your attempt to delete will be rejected, to prevent you from accidentally destroying changes you've not yet seen.

Primo, non si può effettuare la commit della cancellazione di un file o directory che non sia completamente aggiornato. Se nel repository esiste una versione più recente, il tentativo di eliminazione verrà rifiutato, per evitare la distruzione accidentale di modifiche che non si siano ancora viste.

Second, you cannot commit a metadata change to a directory unless it's fully up-to-date. You'll learn about attaching properties to items in Chapter 6. A directory's working revision defines a specific set of entries and properties, and thus committing a property change to an out-of-date directory may destroy properties you've not yet seen.

Secondo, non è possibile effettuare la commit della modifica di un metadato su una directory senza che questa sia completamente aggiornata. Nel capitolo 6 si imparerà ad assegnare «proprietà» agli oggetti. La revisione di lavoro di una directory definisce un insieme specifico di voci e proprietà, quindi effettuare la commit della modifica di una proprietà a una directory non aggiornata potrebbe distruggere qualche proprietà che non sia ancora stata esaminata.