Copiare modifiche tra i rami

Now you and Sally are working on parallel branches of the project: you're working on a private branch, and Sally is working on the trunk, or main line of development.

Adesso voi e Sally state lavorando sui rami paralleli del progetto: voi lavorate su un ramo privato e Sally lavora su tronco (trunk), o linea principale dello sviluppo.

For projects that have a large number of contributors, it's common for most people to have working copies of the trunk. Whenever someone needs to make a long-running change that is likely to disrupt the trunk, a standard procedure is to create a private branch and commit changes there until all the work is complete.

Per progetti che hanno grande numero di contribuenti, è comune per molta gente di avere copie di lavoro del tronco. Ogni volta che qualcuno ha bisogno di fare durature modifiche, che potrebbero disturbare il tronco, procedura standard è di creare un ramo privato e pubblicare le modifiche là finché tutto il lavoro no è completo.

So, the good news is that you and Sally aren't interfering with each other. The bad news is that it's very easy to drift too far apart. Remember that one of the problems with the crawl in a hole strategy is that by the time you're finished with your branch, it may be near-impossible to merge your changes back into the trunk without a huge number of conflicts.

Allora, la notizia buona è che voi e Sally non vi disturbate a vicenda. La cativa è che è molto facile slittare tropo lontano. Ricordate che uno dei problemi della strategia «nascondersi in una buca» è che quando avrete finito con il vostro ramo, potrebbe essere quasi impossibile fondere vostre modifiche nel tronco principale senza largo numero di conflitti.

Instead, you and Sally might continue to share changes as you work. It's up to you to decide which changes are worth sharing; Subversion gives you the ability to selectively copy changes between branches. And when you're completely finished with your branch, your entire set of branch changes can be copied back into the trunk.

Invece, voi e Sally potette continuare di scambiarsi modifiche mentre lavorate. Spetta a voi decidere qualle modifiche vale la pena condividere; Subversion vi dà l'abilità di «copiare» modifiche tra i rami selettivamente. E quando avrete completamente finito con il vostro ramo, vostro completto insieme di modifiche del ramo può essere copiato dietro nel tronco.

Copiare modifiche specifiche

In the previous section, we mentioned that both you and Sally made changes to integer.c on different branches. If you look at Sally's log message for revision 344, you can see that she fixed some spelling errors. No doubt, your copy of the same file still has the same spelling errors. It's likely that your future changes to this file will be affecting the same areas that have the spelling errors, so you're in for some potential conflicts when you merge your branch someday. It's better, then, to receive Sally's change now, before you start working too heavily in the same places.

Nella precedente sezione, abbiamo menzionato che entrambi, voi e Sally avete fatto modifiche su integer.c nei rami diversi. Se date un sguardo al messaggio di log di Sally (versione 344), potete vedere che ella ha corretto qualche errore di battitura. Senza dubbio, vostra copia dello stesso file ancora ha gli stessi errori. È probabile che le vostre future modifiche al file toccheranno gli stessi posti che hanno errori di battitura, così sorgeranno alcuni potenziali conflitti, quando un giorno andrete a fondere il vostro ramo. Meglio incorporare le modifiche di Sally adesso, prima che cominciate lavoro troppo pesante sugli stessi posti.

It's time to use the svn merge command. This command, it turns out, is a very close cousin to the svn diff command (which you read about in Chapter 3). Both commands are able to compare any two objects in the repository and describe the differences. For example, you can ask svn diff to show you the exact change made by Sally in revision 344:

È ora di usare comando svn merge. Questo comando, come si vedrà, è cugino molto stretto del comando svn diff (di quale avete letto nel Capitolo 3). Entrambi comandi sono capaci di comparare qualsiasi due oggetti in deposito(repository) e descrivere le differenze. Per esempio, potete chiedere a svn diff di mostrare esatta modifica fatta da Sally nella versione 344:

$ svn diff -r 343:344 http://svn.example.com/repos/calc/trunk

Index: integer.c
===================================================================
--- integer.c   (revision 343)
+++ integer.c   (revision 344)
@@ -147,7 +147,7 @@
     case 6:  sprintf(info->operating_system, "HPFS (OS/2 or NT)"); break;
     case 7:  sprintf(info->operating_system, "Macintosh"); break;
     case 8:  sprintf(info->operating_system, "Z-System"); break;
-    case 9:  sprintf(info->operating_system, "CPM"); break;
+    case 9:  sprintf(info->operating_system, "CP/M"); break;
     case 10:  sprintf(info->operating_system, "TOPS-20"); break;
     case 11:  sprintf(info->operating_system, "NTFS (Windows NT)"); break;
     case 12:  sprintf(info->operating_system, "QDOS"); break;
@@ -164,7 +164,7 @@
     low = (unsigned short) read_byte(gzfile);  /* read LSB */
     high = (unsigned short) read_byte(gzfile); /* read MSB */
     high = high << 8;  /* interpret MSB correctly */
-    total = low + high; /* add them togethe for correct total */
+    total = low + high; /* add them together for correct total */

     info->extra_header = (unsigned char *) my_malloc(total);
     fread(info->extra_header, total, 1, gzfile);
@@ -241,7 +241,7 @@
      Store the offset with ftell() ! */

   if ((info->data_offset = ftell(gzfile))== -1) {
-    printf("error: ftell() retturned -1.\n");
+    printf("error: ftell() returned -1.\n");
     exit(1);
   }

@@ -249,7 +249,7 @@
   printf("I believe start of compressed data is %u\n", info->data_offset);
   #endif

-  /* Set postion eight bytes from the end of the file. */
+  /* Set position eight bytes from the end of the file. */

   if (fseek(gzfile, -8, SEEK_END)) {
     printf("error: fseek() returned non-zero\n");
  $ svn diff -r 343:344 http://svn.example.com/repos/calc/trunk

  Index: integer.c
  ===================================================================
  --- integer.c   (revision 343)
  +++ integer.c   (revision 344)
  @@ -147,7 +147,7 @@
  case 6:  sprintf(info->operating_system, "HPFS (OS/2 or NT)"); break;
  case 7:  sprintf(info->operating_system, "Macintosh"); break;
  case 8:  sprintf(info->operating_system, "Z-System"); break;
  -    case 9:  sprintf(info->operating_system, "CPM"); break;
  +    case 9:  sprintf(info->operating_system, "CP/M"); break;
  case 10:  sprintf(info->operating_system, "TOPS-20"); break;
  case 11:  sprintf(info->operating_system, "NTFS (Windows NT)"); break;
  case 12:  sprintf(info->operating_system, "QDOS"); break;
  @@ -164,7 +164,7 @@
  low = (unsigned short) read_byte(gzfile);  /* read LSB */
  high = (unsigned short) read_byte(gzfile); /* read MSB */
  high = high << 8;  /* interpreta MSB correttamente */
  -    total = low + high; /* sommali inseme per un totale corretto */
  +    total = low + high; /* sommali insieme per un totale corretto */

  info->extra_header = (unsigned char *) my_malloc(total);
  fread(info->extra_header, total, 1, gzfile);
  @@ -241,7 +241,7 @@
  Memorizza offset con ftell() ! */

  if ((info->data_offset = ftell(gzfile))== -1) {
  -    printf("errore: ftell() ha resttituito -1.\n");
  +    printf("errore: ftell() ha restituito -1.\n");
  exit(1);
  }

  @@ -249,7 +249,7 @@
  printf("Credo che inizio dei dati compressi è %u\n", info->data_offset);
  #endif

  -  /* Imposta poszione otto byte dalla fine del file. */
  +  /* Imposta posizione otto byte dalla fine del file. */

  if (fseek(gzfile, -8, SEEK_END)) {
  printf("errore: fseek() ha restituito non-zero\n");

The svn merge command is almost exactly the same. Instead of printing the differences to your terminal, however, it applies them directly to your working copy as local modifications:

Il comando svn merge è quasi esattamente uguale. Invece di mostrare le differenze sullo schermo, tuttavia, le applica direttamente nella vostra copia di lavoro come modifiche locali:

$ svn merge -r 343:344 http://svn.example.com/repos/calc/trunk
U  integer.c

$ svn status
M  integer.c

The output of svn merge shows that your copy of integer.c was patched. It now contains Sally's change—the change has been copied from the trunk to your working copy of your private branch, and now exists as a local modification. At this point, it's up to you to review the local modification and make sure it works correctly.

L'output di svn merge mostra che vostra copia di integer.c era stata modificata. Adesso contiene le modifiche di Sally—le modifiche erano state «copiate» dal tronco nella copia di lavoro del vostro ramo privato e adesso esistono come modifiche locali. A questo punto, tocca a voi rivedere le modifiche locali ed assicurare che funzionano correttamente.

In another scenario, it's possible that things may not have gone so well, and that integer.c may have entered a conflicted state. You might need to resolve the conflict using standard procedures (see Chapter 3), or if you decide that the merge was a bad idea altogether, simply give up and svn revert the local change.

In un altro scenario, è possibile che le cose possono non andare così bene e perciò integer.c può entrare nello stato di conflitto. Potette avere bisogno di risolvere il conflitto usando procedure standard (vedi Capitolo 3), oppure se decidete che fusione era del tutto una cativa idea, semplicemente passare sopra e scartare con svn revert le modifiche locali.

But assuming that you've reviewed the merged change, you can svn commit the change as usual. At that point, the change has been merged into your repository branch. In version control terminology, this act of copying changes between branches is commonly called porting changes.

Ma assumendo che avete ispezionato le modifiche incorporate, potete pubblicarle con svn commit come al solito. A questo punto, la modifica sarà fusa dentro il vostro ramo del deposito(repository). Nella terminologia di controlo delle versioni, questo atto di copiatura delle modifiche tra i rami è comunemnte chaimato porting dele modifiche.

When you commit the local modification, make sure your log message mentions that you're porting a specific change from one branch to another. For example:

Facendo commit delle modifiche locali, assicuratevi che vostro messaggio menziona che state portando una modifica specifica da un ramo ad altro. Per esempio:

$ svn commit -m "integer.c: ported r344 (spelling fixes) from trunk."
Sending        integer.c
Transmitting file data .
Committed revision 360.
  $ svn commit -m "integer.c: portata r344 (fix di ortografia) dal tronco."
  Sending        integer.c
  Transmitting file data .
  Committed revision 360.

As you'll see in the next sections, this is a very important best practice to follow.

Come vedrete nella prossima sezione, questa è molto importante «regola d'arte» da seguire.

A word of warning: while svn diff and svn merge are very similar in concept, they do have different syntax in many cases. Be sure to read about them in Chapter 9 for details, or ask svn help. For example, svn merge requires a working-copy path as a target, i.e. a place where it should apply the tree-changes. If the target isn't specified, it assumes you are trying to perform one of the following common operations:

Una parola di avvertimento: anche se svn diff e svn merge sono nel concetto molto simili, hanno in molti casi la sintassi diversa. Assicuratevi di leggere dettagli nel Capitolo 9 o chiedete lumi a svn help. Per esempio, svn merge richiede percorso di copia di lavoro come destinazione, i.e. un posto dove può applicare le modifiche della struttura. Se la destinazione non è specificata, assume che state provando di fare una delle seguenti comuni operazioni:

  1. You want to merge directory changes into your current working directory.

    Volete fondere modifiche delle cartelle nella vostra cartella di lavoro.

  2. You want to merge the changes in a specific file into a file by the same name which exists in your current working directory.

    Volete fondere le modifiche d'un file specifico dentro un file con lo stesso nome che esiste nella vostra cartella di lavoro.

If you are merging a directory and haven't specified a target path, svn merge assumes the first case above and tries to apply the changes into your current directory. If you are merging a file, and that file (or a file by the same name) exists in your current working directory, svn merge assumes the second case and tries to apply the changes to a local file with the same name.

Se state fondendo una cartella e non avete specificato percorso di destinazione, svn merge assume il primo caso sopra e prova applicare le modifiche dentro vostra cartella attuale. Se state fondendo un file e questo file (o un file con lo stesso nome) esiste dentro vostra cartella attuale, svn merge assume il secondo caso e prova applicare le modifiche dentro file locale con lo stesso nome.

If you want changes applied somewhere else, you'll need to say so. For example, if you're sitting in the parent directory of your working copy, you'll have to specify the target directory to receive the changes:

Se volete applicare le modifiche in un altro posto, dovete dirlo. Per esempio, se siete nella cartella parente della vostra copia di lavoro, dovete specificare cartella destinazione per ricevere le modifiche:

$ svn merge -r 343:344 http://svn.example.com/repos/calc/trunk my-calc-branch
U   my-calc-branch/integer.c

Concetto chiave dietro la fusione

You've now seen an example of the svn merge command, and you're about to see several more. If you're feeling confused about exactly how merging works, you're not alone. Many users (especially those new to version control) are initially perplexed about the proper syntax of the command, and about how and when the feature should be used. But fear not, this command is actually much simpler than you think! There's a very easy technique for understanding exactly how svn merge behaves.

Abbiamo visto un esempio di comando svn merge, e stiamo per vedere di più. Se vi sentite confusi riguardo come funziona esattamente la fusione, non siete soli. Molti utenti (specialmente quelli nuovi a cotrollo delle versioni) rimangono inizialmente perplessi riguardo la giusta sintassi del comando e come e quando usare questa caratteristica. Non avere paura, questo comando è in verità molto più semplice che si pensa. C'è una tecnica molto semplice per capire esattamente come svn merge agisce.

The main source of confusion is the name of the command. The term merge somehow denotes that branches are combined together, or that there's some sort of mysterious blending of data going on. That's not the case. A better name for the command might have been svn diff-and-apply, because that's all that happens: two repository trees are compared, and the differences are applied to a working copy.

La fonte primaria della confusione è il nome del comando. Il termine «merge»(fondere) qualche volta denota che i rami sono combinati tra loro, oppure che ci sta qualche sorta di misterioso mescolamento dei dati. Non è il caso. Più appropriato nome per questo comando forse sarebbe svn diff-and-apply(trova-differenze-e-applicale), perché questo è tutto che accade: due strutture del deposito(repository) sono comparate e le differenze sono applicate alla copia di lavoro.

The command takes three arguments:

Il comando prende tre argomenti:

  1. An initial repository tree (often called the left side of the comparison),

    Una struttura del deposito(repository) iniziale (spesso chiamata il lato sinistro della comparazione),

  2. A final repository tree (often called the right side of the comparison),

    Una struttura del deposito(repository) finale (spesso chiamata il lato destro della comparazione),

  3. A working copy to accept the differences as local changes (often called the target of the merge).

    Una copia di lavoro per ricevere le differenze come modifiche locali (spesso chiamata la destinazione della fusione).

Once these three arguments are specified, the two trees are compared, and the resulting differences are applied to the target working copy as local modifications. When the command is done, the results are no different than if you had hand-edited the files, or run various svn add or svn delete commands yourself. If you like the results, you can commit them. If you don't like the results, you can simply svn revert all of the changes.

Una volta specificati questi tre argomenti, le due strutture sono comparate e le differenze risultanti sono applicate alla copia di lavoro destinataria come modifiche locali. Quando il comando finisce il suo lavoro, il risultato non è diverso da come aveste editato i file manualmente o aveste da soli avviato svariati comandi svn add o svn delete. Se il risultato vi piace, potete fare commit. Se non vi piace, con semplice comando svn revert scartate tutte le modifiche.

The syntax of svn merge allows you to specify the three necessary arguments rather flexibly. Here are some examples:

La sintassi di comando svn merge vi permete di specificare i tre argomenti necessari in modo molto flessibile Qui ci sono alcuni esempi:

$ svn merge http://svn.example.com/repos/branch1@150 \
            http://svn.example.com/repos/branch2@212 \
            my-working-copy

$ svn merge -r 100:200 http://svn.example.com/repos/trunk my-working-copy

$ svn merge -r 100:200 http://svn.example.com/repos/trunk

The first syntax lays out all three arguments explicitly, naming each tree in the form URL@REV and naming the working copy target. The second syntax can be used as a shorthand for situations when you're comparing two different revisions of the same URL. The last syntax shows how the working-copy argument is optional; if omitted, it defaults to the current directory.

La prima sintassi elenca tutti e tre argomenti esplicitamente, nominando ogni struttura in forma URL@REV e nominando la copia di lavoro ricevente. La seconda sintassi può essere usata, quando state comparando due versioni diverse dello stesso URL. L'ultima sintassi mostra che argomento 'copia di lavoro' è facoltativo; se omesso, il suo valore predefinito è la cartella attuale.

Regole d'arte per la fusione

Tenere a mano traccia delle fusioni

Merging changes sounds simple enough, but in practice it can become a headache. The problem is that if you repeatedly merge changes from one branch to another, you might accidentally merge the same change twice. When this happens, sometimes things will work fine. When patching a file, Subversion typically notices if the file already has the change, and does nothing. But if the already-existing change has been modified in any way, you'll get a conflict.

Fondere modifiche suona abbastanza semplice, ma in prattica può diventare mal di testa. Il problema è che se ripetutamente fondete modifiche da un ramo ad altro, potete accidentalmente fondere la stessa modifica due volte. Se succede questo, a volte tutto va bene. Quando Subversion applica le modifiche su un file, tipicamente si accorge che il file queste modifiche ha già e non fa niente. Ma se la già esistente modifica era ulteriormente modificata, otente un conflitto.

Ideally, your version control system should prevent the double-application of changes to a branch. It should automatically remember which changes a branch has already received, and be able to list them for you. It should use this information to help automate merges as much as possible.

Idealmente, vostro sistema di controlo delle versioni dovrebbe prevenire la doppia applicazione delle modifiche su un ramo. Dovrebbe automaticamente ricordare quale modifiche il ramo ha già ricevuto ed essere capace di elencarle per voi. Dovrebbe usare queste informazioni per automatizzare le fusioni quanto più possibile.

Unfortunately, Subversion is not such a system. Like CVS, Subversion does not yet record any information about merge operations. When you commit local modifications, the repository has no idea whether those changes came from running svn merge, or from just hand-editing the files.

Sfortunatamente, un sistema così non è Subversion. Come il CVS, Subversion non memorizza ancora nessuna informazione riguardo operazioni di fusioni. Quando fatte commit delle modifiche locali, il deposito(repository) non ha idea se queste modifiche arrivano da svn merge eseguito o da editazione a mano dei file.

What does this mean to you, the user? It means that until the day Subversion grows this feature, you'll have to track merge information yourself. The best place to do this is in the commit log-message. As demonstrated in the earlier example, it's recommended that your log-message mention a specific revision number (or range of revisions) that are being merged into your branch. Later on, you can run svn log to review which changes your branch already contains. This will allow you to carefully construct a subsequent svn merge command that won't be redundant with previously ported changes.

Che cosa significa questo per voi, utente? Significa che fino al giorno in cui Subversion avrà questa capacità, dovete tracciare informazioni riguardo le fusioni da soli. Il posto migliore dove farlo è messaggio di commit. Come era dimostrato nel esempio precedente, è raccomandato che vostro messaggio menziona specifico numero della revisione (o rango delle revisioni) che state fondendo nel vostro ramo. In futuro potete avviare comando svn log per vedere quale modifiche contiene già il vostro ramo. Questo vi permete di costruire con cura prossimi comandi svn merge che non saranno redundanti con le modifiche già riportate in precedenza.

In the next section, we'll show some examples of this technique in action.

Nella prossima sezione mostreremo in azione alcuni esempi di questa tecnica.

Anteprima delle fusioni

Because merging only results in local modifications, it's not usually a high-risk operation. If you get the merge wrong the first time, simply svn revert the changes and try again.

Perché risultato delle fusioni sono soltanto le modifiche locali, questa non è normalmente una operazione ad alto rischio. Se vi capita di fondere male prima volta, semplicemente buttate via le modifiche (svn revert) e provate di nuovo.

It's possible, however, that your working copy might already have local modifications. The changes applied by a merge will be mixed with your pre-existing ones, and running svn revert is no longer an option. The two sets of changes may be impossible to separate.

È possibile, comunque, che vostra copia di lavoro contiene anche le modifiche locali. Le modifiche applicate da merge saranno mischiate tra le vostre e avviare comando svn revert non è più una scelta pratticabile. Potrebbe essere impossibile separare i due insiemi delle modifiche.

In cases like this, people take comfort in being able to predict or examine merges before they happen. One simple way to do that is to run svn diff with the same arguments you plan to pass to svn merge, as we already showed in our first example of merging. Another method of previewing is to pass the --dry-run option to the merge command:

In casi come questo, le persone si confortano con la possibilità di prevedere o esaminare fusione prima che accade. Un semplice modo per farlo è avviare svn diff con gli stessi argomenti che avete in mente di passare a svn merge, come abbiamo già mostrato nel nostro primo esempio. Altro metodo di anteprima è aggiungere la opzione --dry-run(a secco) al comando merge:

$ svn merge \-\-dry-run -r 343:344 http://svn.example.com/repos/calc/trunk
U  integer.c

$ svn status
#  nothing printed, working copy is still unchanged.
  $ svn merge --dry-run -r 343:344 http://svn.example.com/repos/calc/trunk
  U  integer.c

  $ svn status
  # non stampa niente, copia di lavoro è ancora intatta.

The --dry-run option doesn't actually apply any local changes to the working copy. It only shows status codes that would be printed in a real merge. It's useful for getting a high level preview of the potential merge, for those times when running svn diff gives too much detail.

La opzione --dry-run in verità non applica nessuna modifica locale alla copia di lavoro. Mostra solo output che sarebbe mostrato con la fusione vera. Questo è utile per avere una previsione ad «alto livello» della potenziale fusione, per quelle volte dove comando svn diff dà troppi dettagli.

Conflitti delle fusioni

Just like the svn update command, svn merge applies changes to your working copy. And therefore it's also capable of creating conflicts. The conflicts produced by svn merge, however, are sometimes different, and this section explains those differences.

Così come comando svn update, anche svn merge applica modifiche alla vostra copia di lavoro. E perciò è capace generare conflitti. I conflitti prodotti da svn merge, tuttavia, sono a volte diversi e questa sezione spiega queste differenze.

To begin with, assume that your working copy has no local edits. When you svn update to a particular revision, the changes sent by the server will always apply cleanly to your working copy. The server produces the delta by comparing two trees: a virtual snapshot of your working copy, and the revision tree you're interested in. Because the left-hand side of the comparison is exactly equal to what you already have, the delta is guaranteed to correctly convert your working copy into the right-hand tree.

Per cominciare, si assume che vostra copia di lavoro non ha editazioni locali. Quando la aggiornate (svn update) ad una particolare versione, le modifiche mandate dal server si applicano sempre alla vostra copia di lavoro in modo «pulito». Il server produce un ??delta? comparando due strutture: un'instantanea virtuale della vostra copia di lavoro e struttura della revisione a quale siete interessati. Perché lato sinistra della comparazione è uguale a quel che già avete il delta garantisce di correttamente convertire vostra copia di lavoro nella struttura di lato destra.

But svn merge has no such guarantees and can be much more chaotic: the user can ask the server to compare any two trees at all, even ones that are unrelated to the working copy! This means there's large potential for human error. Users will sometimes compare the wrong two trees, creating a delta that doesn't apply cleanly. svn merge will do its best to apply as much of the delta as possible, but some parts may be impossible. Just like the Unix patch command sometimes complains about failed hunks, svn merge will complain about skipped targets:

Ma svn merge non ha tali garanzie e può essere più caotico: utente può chidere al server di comparare qualsiasi due strutture, anche tali che non hanno nessun legame con la copia di lavoro. Questo significa che qui c'è largo potenziale per errori umani. Utenti possono a volte comparare due strutture sbagliate, creando delta che non si applica pulitamente. svn merge farà il meglio per applicare più possibile il delta, ma su alcune parti questo potrà essere impossibile. Nello stesso modo come comando Unix patch a volte si lamenta di ??«failed hunks»?, svn merge può accusare «skipped targets» (destinazioni saltate):

$ svn merge -r 1288:1351 http://svn.example.com/repos/branch
U  foo.c
U  bar.c
Skipped missing target: 'baz.c'
U  glub.c
C  glorb.h

$

In the previous example it might be the case that baz.c exists in both snapshots of the branch being compared, and the resulting delta wants to change the file's contents, but the file doesn't exist in the working copy. Whatever the case, the skipped message means that the user is most likely comparing the wrong two trees; they're the classic sign of driver error. When this happens, it's easy to recursively revert all the changes created by the merge (svn revert --recursive), delete any unversioned files or directories left behind after the revert, and re-run svn merge with different arguments.

Nel esempio precedente può essere caso che baz.c esiste in entrambe instantanee del ramo comparato e delta risultante vuole cambiare il contenuto del file, ma il file non esiste nella copia di lavoro. Qualunque sia causa, il messaggio «skipped»(saltato) significa che con alta probabilità utente sta comparando le strutture sbagliate; questo è un segno classico del 'errore del conducente'. Quando accade ciò, è semplice invertire ricorsivamente tutte le modifiche create dalla fusione (svn revert --recursive), cancellare ogni file o cartella rimasta senza controllo delle versioni dopo revert e rifare svn merge con argomenti diversi.

Also notice that the previous example shows a conflict happening on glorb.h. We already stated that the working copy has no local edits: how can a conflict possibly happen? Again, because the user can use svn merge to define and apply any old delta to the working copy, that delta may contain textual changes that don't cleanly apply to a working file, even if the file has no local modifications.

Notare ancora che precedente esempio mostra un conflitto accaduto su glorb.h. Abbiamo già stabilito che copia di lavoro non ha editazioni locali: come può allora accadere un conflitto? Di nuovo, perché l'utente può usare svn merge per definire ed applicare qualsiasi delta vecchio a copia di lavoro, tale delta può contenere modifiche testuali che non si applicano in modo pulito al file di lavoro, anche se il file non ha le modifiche locali.

Another small difference between svn update and svn merge are the names of the full-text files created when a conflict happens. In sezione chiamata «Risolvere i conflitti(Mettere insieme i cambiamenti operati da altri)», we saw that an update produces files named filename.mine, filename.rOLDREV, and filename.rNEWREV. When svn merge produces a conflict, though, it creates three files named filename.working, filename.left, and filename.right. In this case, the terms left and right are describing which side of the double-tree comparison the file came from. In any case, these differing names will help you distinguish between conflicts that happened as a result of an update versus ones that happened as a result of a merge.

Altra piccola differenza tra svn update e svn merge sono i nomi dei file testuali creati quando accade un conflitto. Nella sezione chiamata «Risolvere i conflitti(Mettere insieme i cambiamenti operati da altri)», abbiamo visto che un aggiornamento (update) produce file nominati filename.mine, filename.rOLDREV e filename.rNEWREV. Quando comando svn merge produce un conflitto, ??though?, crea tre file nominati filename.working, filename.left e filename.right. Qui i termini «left» e «right» descrivono da quale lato della comparazione delle strutture proviene il file. In qualsiasi caso, questi nomi diversi vi aiuteranno distinguere tra conflitti che accadono come risultato d'un aggiornamento (update) e tali che accadono come risultato d'una fusione (merge).

Notare o ignorare ascendenza

When conversing with a Subversion developer, you might very likely hear reference to the term ancestry. This word is used to describe the relationship between two objects in a repository: if they're related to each other, then one object is said to be an ancestor of the other.

Parlando con sviluppatori di Subversion, uno può molto probabilmente sentire riferimento al termine ascendenza(ancestry). Questa parola è usata per descrivere la relazione tra due oggetti nel deposito(repository): se sono in relazione si dice che uno è antenato dell'altro.

For example, suppose you commit revision 100, which includes a change to a file foo.c. Then foo.c@99 is an ancestor of foo.c@100. On the other hand, suppose you commit the deletion of foo.c in revision 101, and then add a new file by the same name in revision 102. In this case, foo.c@99 and foo.c@102 may appear to be related (they have the same path), but in fact are completely different objects in the repository. They share no history or ancestry.

Per esempio, supponiamo che voi depositate la versione 100, che include una modifica a file foo.c. Dopo questo il file foo.c@99 è un «antenato» di foo.c@100. Caso oposto, supponiamo che depositate la cancellazione del foo.c nella versione 101 e dopo aggiugete nuovo file con lo stesso nome nella versione 102. In questo caso, foo.c@99 e foo.c@102 possono apparire in relazione (hanno lo stesso percorso e nome), ma in verità sono oggetti del deposito(repository) completamente diversi. Non condividono nessuna storia o «ascendenza».

The reason for bringing this up is to point out an important difference between svn diff and svn merge. The former command ignores ancestry, while the latter command is quite sensitive to it. For example, if you asked svn diff to compare revisions 99 and 102 of foo.c, you would see line-based diffs; the diff command is blindly comparing two paths. But if you asked svn merge to compare the same two objects, it would notice that they're unrelated and first attempt to delete the old file, then add the new file; the output would indicate a deletion followed by an add:

La ragione per spiegare questo è di puntare il dito sulla differenza importante tra svn diff e svn merge. Il primo comando ignora ascendenza, invece il secondo è assai sensibile ad essa. Per esempio, chiedendo a svn diff di comparare revisioni 99 e 102 di foo.c, potete vedere differenze basate sulle linee; il comando diff ciecamente compara i due file. Ma se chiedete a svn merge di comparare gli stessi oggetti, lui si accorge che non sono in relazione e prima provede a cancellare quello vecchio e poi aggiunge nuovo; output indicherà una cancellazione seguita da una aggiunta:

D  foo.c
A  foo.c

Most merges involve comparing trees that are ancestrally related to one another, and therefore svn merge defaults to this behavior. Occasionally, however, you may want the merge command to compare two unrelated trees. For example, you may have imported two source-code trees representing different vendor releases of a software project (see sezione chiamata «Vendor branches»). If you asked svn merge to compare the two trees, you'd see the entire first tree being deleted, followed by an add of the entire second tree!

Molte fusioni coinvolgono comparazioni delle strutture che sono genealogicamente relazionate tra loro, e perciò svn merge ha come predefinito questo comportamento. Occasionalmente, tuttavia, si può volere che comando merge compara due strutture che non sono in relazione. Per esempio, si può importare due strutture del codice sorgente che rappresentano due rilasci pubblici d'un progetto software (vedi la sezione chiamata «Vendor branches»). Chiedendo a svn merge di comparare queste due strutture, si vede prima la cancellazione completta della prima struttura, seguita da aggiunta di tutta la seconda struttura!

In these situations, you'll want svn merge to do a path-based comparison only, ignoring any relations between files and directories. Add the --ignore-ancestry option to your merge command, and it will behave just like svn diff. (And conversely, the --notice-ancestry option will cause svn diff to behave like the merge command.)

In tali situazioni, si chiede a svn merge di fare comparazione basata solo sui nomi, ignorando qualsiasi relazione tra i file e cartelle. Si aggiunge opzione --ignore-ancestry al vostro comando di fusione, e quello si comporterà esattamente come svn diff. (E al contrario, la opzione --notice-ancestry causerà che svn diff aggirà come comando merge.)



[17] In the future, the Subversion project plans to use (or invent) an expanded patch format that describes changes in tree structure and properties.

[18] In futuro, progetto Subversion pianifica du usare (o inventare) patch format estesso che descrive modifiche delle struture e properietà.