2012-09-17 12 views
7

In Mercurial, i numeri di revisione sono specifici per clone locale e vengono forniti come una funzione per indicare un changeset specifico in un modo più intuitivo rispetto a un id del changeset.È possibile modificare/riordinare manualmente i numeri di revisione (la topologia fornita rimane la stessa)?

Tuttavia, durante la visualizzazione del grafico della timeline, TortoiseHG ordinerà per numero di revisione. Se un ragazzo spinge i commit non così spesso, avrai tutti i suoi commit in una volta con numeri di revisione adiacenti, e rovinerà l'intero punto del grafico.

enter image description here

Questo grafico sarebbe più penetranti: ci sono due linee di sviluppo, con due autori, una fusione del lavoro dell'altra:

enter image description here

Pertanto, è possibile per riordinare manualmente i numeri di revisione (purché the topological order of changesets sia ancora compatibile con i nuovi numeri?

Grazie.

+1

ammettere, non vedo il problema. Il grafico mostra la topologia. Il timing del mondo reale dei commit è secondario. –

+2

@Paul S: quando hai molte linee trasversali nel tuo grafico, possono essere difficili da seguire. Lo spostamento commette 404-405 tra i comandi 370-371 e 406 subito dopo 371, 407 subito dopo 380, 408 e 409 subito dopo 399, produrrebbe un grafico di larghezza minore (due colonne in realtà). – Benoit

+0

@Paul S: vedi modifica. Non vedi che quello è davvero più chiaro e ha la stessa topologia esatta? – Benoit

risposta

1

È possibile riordinare il repository (è ciò che fa contrib/shrink-revlog.py). Ma in questo caso sembra eccessivo e complicato.

Poiché si tratta principalmente di un problema di visualizzazione, è preferibile chiedere a THG di implementare il riordino che si desidera avere. Di sicuro non ho idea di cosa trovi incasinato nel grafico qui sopra.

+2

È già in giù come una proposta sul tracker di problemi THG [qui] (https://bitbucket.org/tortoisehg/thg/issue/580/), ma è stato sollevato nell'aprile 2011 quindi suppongo che il team THG don Hanno anche una priorità alta. –

3

Come altri stanno dicendo, è possibile, ma probabilmente non vale il lavoro, dal momento che sarebbe locale per il tuo clone (e qualsiasi clone del tuo clone). Non è qualcosa che potreste spingere su un repository remoto senza eliminare tutto lì prima, e anche se lo faceste, le persone che avevano cloni da quel repository remoto avrebbero visto "nessun cambiamento" quando hanno tirato.

Detto questo, se si desidera provare, è sufficiente utilizzare una serie di comandi hg pull -r REV in un nuovo clone. Qualcosa di simile a questo:

hg init my_reordered_clone 
cd my_reordered_clone 
hg pull -r d84b1 ../un_reordered_clone 
hg pull -r 6d269 ../un_reordered_clone 
hg pull -r bb9e4 ../un_reordered_clone 

Chiaramente questo è troppo lavoro per essere vale la pena per fini estetici, ma il concetto non è che quando si tira con -r si ottiene quel changeset e tutti i suoi antenati, quindi se fate il vostro tira verso i punti in cui i rami anonimi si fondono uno alla volta, tirerai solo i changeset aggiuntivi da quella linea di sviluppo.

+1

Non direi che è troppo lavoro: se conosci l'ordine che vuoi, è solo un semplice ciclo nel tuo linguaggio di scripting preferito. Ho un caso d'uso simile (vedi la mia risposta). – alexis

5

Ho un caso d'uso simile: sono arrivato a questa domanda perché ho spinto un gruppo di changeset da diversi rami contemporaneamente, e non sono arrivati ​​ordinati per data. Ora ho un po 'di fusione con i genitori di basso numero che non sono in realtà così vecchi; scorrere su e giù per il registro per vederli è un dolore. Ho seguito l'approccio suggerito nella risposta di @ Ry4an-- è davvero semplice, se puoi prevedere (vale a dire, calcolare) l'ordine dei changeset che desideri.

Se il flusso di lavoro unisce solo diramazioni, è possibile ottenere l'ordine di revisione desiderato ordinando i giri per data. Questo si può fare con il seguente comando:

hg log -r 'sort(0:tip, date)' --template '{rev}\n' 

È quindi possibile clonare il repository e utilizzare un ciclo nella tua linguaggio di scripting preferito per tirare la revisione uno ad uno in ordine cronologico.Invece di init un repository da zero, ho finito per fare in questo modo:

hg clone -r 0 messy-repo sorted-repo 
cd sorted-repo 
for REV in `hg log -R ../messy-repo -r 'sort(1:tip, date)' --template '{rev}\n'` 
do 
    hg pull ../messy-repo -r $REV 
done 

Vorrei sottolineare (prima che qualcun altro fa :-)) che questo aumentare le dimensioni di archiviazione del repository, a causa di il modo in cui vengono calcolati i delta. Non mi dispiace.

+0

Questo è quasi perfetto, tranne che mette sempre la revisione 0 all'inizio del nuovo repository, quindi se anche questo è fuori servizio, ciò non verrà risolto. Per risolvere questo, usa 'hg init' invece di' hg clone ... ', poi cambia' ... sort (1: tip, date) ... 'per' ... sort (:, date) .. .'. –

1

Di seguito è un'implementazione di ridurre la larghezza grafico utilizzando un csscript

Il comando per copiare il pronti contro termine con la storia riordinato è

cs-script\cscs.exe HgSortMergeChangesets.cs fromRepo toNewRepo 

Il file "HgSortMergeChangesets.cs" ha il seguente contenuto:

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.IO; 
using System.Linq; 

class Program 
{ 
    static int Main(string[] args) 
    { 
     if (args.Length != 2) 
     { 
      Console.WriteLine("usage: SortHgRepo <fromRepo> <toRepo>"); 
      return -1; 
     } 

     var fromRepo = new DirectoryInfo(args[0]); 
     var toRepo = new DirectoryInfo(args[1]); 


     int errorCode = VerifyParameters(toRepo, fromRepo); 
     if (errorCode != 0) 
     { 
      return errorCode; 
     } 

     var revsOutput = ExecCmdReturnStdOut("hg.exe", "log -r \"sort(merge(),date)\" -T \"{rev} {date|date}\\n\"", fromRepo.FullName, Console.WriteLine); 

     var mergeChangesets = ParseChangesetLog(revsOutput) 
      .ToList(); 

     ExecCmdReturnStdOut("hg.exe", string.Format("clone -U -r 0 . \"{0}\"", toRepo.FullName), fromRepo.FullName, Console.WriteLine); 

     foreach (var changeset in mergeChangesets) 
     { 
      ExecCmdReturnStdOut("hg.exe", string.Format("pull \"{1}\" -r {0}", changeset.ChangesetId, fromRepo.FullName), toRepo.FullName, Console.WriteLine); 
     } 

     ExecCmdReturnStdOut("hg.exe", string.Format("pull \"{0}\"", fromRepo.FullName), toRepo.FullName, Console.WriteLine); 

     return 0; 

    } 

    private static int VerifyParameters(DirectoryInfo toRepo, DirectoryInfo fromRepo) 
    { 
     if (toRepo.Exists) 
     { 
      Console.WriteLine("The destination repo already exists: {0}", toRepo); 
      { 
       return -2; 
      } 
     } 


     if (!fromRepo.Exists) 
     { 
      Console.WriteLine("The source repo does not exists: {0}", fromRepo); 
      { 
       return -3; 
      } 
     } 

     // make sure the source dir is a repo 
     try 
     { 
      var identity = ExecCmdReturnStdOut("hg.exe", "identify", fromRepo.FullName, Console.WriteLine); 
      Console.WriteLine(identity); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.Message); 
      Console.WriteLine("The source directory, {0}, does not look like an Hg repo.", fromRepo); 
      return -4; 
     } 
     return 0; 
    } 


    private static IEnumerable<Changeset> ParseChangesetLog(string revsOutput) 
    { 
     using (var r = new StringReader(revsOutput)) 
     { 
      string line; 
      while ((line = r.ReadLine()) != null) 
      { 
       var spacePos = line.IndexOf(' '); 
       yield return new Changeset 
       { 
        ChangesetId = int.Parse(line.Substring(0, spacePos)), 
        DateStr = line.Substring(spacePos + 1) 
       }; 
      } 
     } 
    } 

    class Changeset 
    { 
     public int ChangesetId; 
     public string DateStr; 
     public DateTime Date { get { return DateTime.ParseExact(DateStr, "ddd MMM dd H:mm:ss yyyy zzz", null); } } 
    } 



    public static string ExecCmdReturnStdOut(string program, string args, string workingDir, Action<string> writeline) 
    { 

     writeline(String.Format("Executing: \"{0}\" {1} in {2}", program, args, workingDir)); 

     using (var proc = new Process()) 
     { 

      proc.StartInfo.Arguments = args; 
      proc.StartInfo.CreateNoWindow = false; 
      proc.StartInfo.FileName = program; 
      proc.StartInfo.WorkingDirectory = workingDir; 
      proc.StartInfo.RedirectStandardError = false; 
      proc.StartInfo.RedirectStandardOutput = true; 
      proc.StartInfo.UseShellExecute = false; 

      proc.Start(); 

      var output = proc.StandardOutput.ReadToEnd(); 

      proc.WaitForExit(); 

      if (proc.ExitCode != 0) 
      { 
       throw new Exception(string.Format("error code {0} returned when running command {1} in dir {2}", proc.ExitCode, "\"" + program + "\" " + args, workingDir)); 
      } 

      return output; 
     } 
    } 


} 
0

credito a causa @alexis e @ Ry4an

Conosco questa soluzione alternativa per creare un nuovo clone ordinato per data e funziona, anche se potrebbe essere lento per i repository di grandi dimensioni. Dipende se consideri che ne vale la pena.

Oggi stavo tirando verso un PC Windows e questo mi ha catturato, quindi volevo automatizzarlo rapidamente. Così qui è una riscrittura per il prompt dei comandi di Windows:

hg clone -r 0 messy-repo sorted-repo 
cd sorted-repo 
for /f "usebackq tokens=*" %r in (`hg log -R ../messy-repo -r "sort(1:tip, date)" --template "{rev}\n"`) do @echo %r && @hg pull ../messy-repo -r %r 

Avviso: segni di percentuale devono essere raddoppiati se questo va all'interno di un file script batch, altrimenti singola per cento per inserire direttamente al prompt dei comandi.

PD: il giusto merito anche a Michael Burr per il backquote per prompt di Windows: windows subcommand evaluation

Problemi correlati