Is it possible to manually change/reorder the revision numbers (provided topology remains the same)?

前端 未结 5 958
再見小時候
再見小時候 2020-12-06 19:01

In Mercurial , revision numbers are local-clone specific, and they are provided as a facility to point to a specific changeset in a more user-friendly way than a changeset i

5条回答
  •  死守一世寂寞
    2020-12-06 19:37

    Below is an implementation to narrow the graph width using a csscript

    The command to copy your repo with the history reordered is

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

    The file "HgSortMergeChangesets.cs" has the following contents:

    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  ");
                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 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, "ffffd MMM dd H:mm:ss yyyy zzz", null); } }
        }
    
    
    
        public static string ExecCmdReturnStdOut(string program, string args, string workingDir, Action 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;
            }
        }
    
    
    }
    

提交回复
热议问题