Repo Migrate Folder With History
void Main() | |
{ | |
var originalRepo = "git@github.com:_**_/_**_.git"; | |
var originalRepoBranch = "master"; | |
var newRepo = "git@github.com:_**_/_**_.git"; | |
var newRepoBranch = "master"; | |
var workInProgressDir = @"C:\Temp\RepoCopy"; | |
var relativeFolderToMigrate = "src/path"; | |
MigrateRepo(originalRepo, originalRepoBranch, newRepo, newRepoBranch, workInProgressDir, relativeFolderToMigrate); | |
} | |
private void MigrateRepo(string originalRepo, string originalRepoBranch, string newRepo, string newRepoBranch, string workInProgressDir, string relativeFolderToMigrate) | |
{ | |
var runId = Guid.NewGuid().ToString(); | |
Console.WriteLine("-----------------------------"); | |
Console.WriteLine($"RunId: {runId}"); | |
var runDirectory = Path.Combine(workInProgressDir, runId); | |
var fromRepoPath = Path.Combine(runDirectory, "FromRepo"); | |
var fromRepoCleanUpPath = Path.Combine(runDirectory, "FromRepoCleanUp"); | |
var toRepoPath = Path.Combine(runDirectory, "ToRepo"); | |
EnsureDirectoryClean(runDirectory); | |
Console.WriteLine("-----------------------------"); | |
Console.WriteLine($"Creating filtered version of {originalRepo}"); | |
RunGit(workInProgressDir, $"clone {originalRepo} {fromRepoPath}"); | |
RunGit(fromRepoPath, "remote rm origin"); | |
RunGit(fromRepoPath, $"checkout {originalRepoBranch}"); | |
RunGit(fromRepoPath, $"filter-branch --subdirectory-filter {relativeFolderToMigrate} -- --all"); | |
Console.WriteLine("-----------------------------"); | |
Console.WriteLine($"Moving {fromRepoPath} content back into the relative folder of {relativeFolderToMigrate}"); | |
var subDirs = Directory.GetDirectories(fromRepoPath); | |
var subFiles = Directory.GetFiles(fromRepoPath); | |
var newLocationRoot = Path.Combine(fromRepoPath, relativeFolderToMigrate); | |
Console.WriteLine($"Creating Dir: {newLocationRoot}"); | |
Directory.CreateDirectory(newLocationRoot); | |
foreach (var subDir in subDirs) | |
{ | |
if(subDir.EndsWith(".git")) continue; | |
var relativeSubDir = subDir.Replace(fromRepoPath, "").Substring(1); | |
var newLocation = Path.Combine(fromRepoPath, relativeFolderToMigrate, relativeSubDir); | |
Console.WriteLine($"Moving Dir: {subDir} -> {newLocation}"); | |
Directory.Move(subDir, newLocation); | |
} | |
foreach (var subFile in subFiles) | |
{ | |
var relativeSubFile = subFile.Replace(fromRepoPath, "").Substring(1); | |
var newLocation = Path.Combine(fromRepoPath, relativeFolderToMigrate, relativeSubFile); | |
Console.WriteLine($"Moving File: {subFile} -> {newLocation}"); | |
File.Move(subFile, newLocation); | |
} | |
RunGit(fromRepoPath, $"add ."); | |
RunGit(fromRepoPath, $"commit -m \"Revert folder structure post filter\""); | |
Console.WriteLine("-----------------------------"); | |
Console.WriteLine($"Merging filtered version of {originalRepo} into {newRepo}"); | |
RunGit(workInProgressDir, $"clone {newRepo} {toRepoPath}"); | |
RunGit(toRepoPath, $"remote add FromRepo {fromRepoPath}"); | |
RunGit(toRepoPath, $"pull FromRepo {originalRepoBranch}", true); | |
RunGit(toRepoPath, $"branch feature/RepoMigrate origin/{newRepoBranch}"); | |
RunGit(toRepoPath, "checkout feature/RepoMigrate"); | |
RunGit(toRepoPath, $"merge FromRepo/{originalRepoBranch} --allow-unrelated-histories"); | |
RunGit(toRepoPath, "remote rm FromRepo"); | |
RunGit(toRepoPath, "push origin feature/RepoMigrate"); | |
Console.WriteLine("-----------------------------"); | |
Console.WriteLine($"Cleaning {originalRepo}"); | |
RunGit(workInProgressDir, $"clone {originalRepo} {fromRepoCleanUpPath}"); | |
RunGit(fromRepoCleanUpPath, "branch feature/RepoMigrate"); | |
RunGit(fromRepoCleanUpPath, "checkout feature/RepoMigrate"); | |
Directory.Delete(Path.Combine(fromRepoCleanUpPath, relativeFolderToMigrate), true); | |
RunGit(fromRepoCleanUpPath, $"add ."); | |
RunGit(fromRepoCleanUpPath, $"commit -a -m \"Remove migrated folder {relativeFolderToMigrate} as moved to {newRepo}\""); | |
RunGit(fromRepoCleanUpPath, "push origin feature/RepoMigrate"); | |
} | |
private void RunGit(string workingDirectory, string args, bool ignoreError = false) | |
{ | |
RunCommand(workingDirectory, "git", args, ignoreError); | |
} | |
private void RunCommand(string workingDirectory, string fileName, string args, bool ignoreError = false) | |
{ | |
Process process = new Process(); | |
Console.WriteLine("-----------------------------"); | |
Console.WriteLine($"WorkingDirectory: {workingDirectory}"); | |
Console.WriteLine($"Exec: {fileName} {args}"); | |
try | |
{ | |
process.StartInfo.FileName = fileName; | |
process.StartInfo.WorkingDirectory = workingDirectory; | |
process.StartInfo.Arguments = args; | |
process.StartInfo.RedirectStandardError = true; | |
process.StartInfo.RedirectStandardOutput = true; | |
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; | |
process.StartInfo.CreateNoWindow = true; | |
process.StartInfo.UseShellExecute = false; | |
process.EnableRaisingEvents = false; | |
process.OutputDataReceived += (sender, eventArgs) => WriteConsoleOutput("stdOut", eventArgs); | |
process.ErrorDataReceived += (sender, eventArgs) => WriteConsoleOutput("stdErr", eventArgs); | |
process.Start(); | |
process.BeginOutputReadLine(); | |
process.BeginErrorReadLine(); | |
process.WaitForExit(); | |
if(process.ExitCode == 0) | |
{ | |
Console.WriteLine($"SUCCESS: Process exited with code of {process.ExitCode}"); | |
} | |
else if (ignoreError) | |
{ | |
Console.WriteLine($"WARN: Process exited with code of {process.ExitCode}"); | |
} | |
else | |
{ | |
Console.WriteLine($"ERROR: Process exited with code of {process.ExitCode}"); | |
throw new Exception($"Process exited with non-zero exit code of {process.ExitCode}"); | |
} | |
} | |
finally | |
{ | |
process.Close(); | |
} | |
} | |
private void WriteConsoleOutput(string type, DataReceivedEventArgs eventArgs) | |
{ | |
if (eventArgs.Data != null) | |
{ | |
Console.WriteLine($"{type} : {eventArgs.Data}"); | |
} | |
} | |
private void EnsureDirectoryClean(string path) | |
{ | |
if (Directory.Exists(path)) | |
{ | |
Console.WriteLine("-----------------------------"); | |
Console.WriteLine($"Directory {path} already exists, delete manually"); | |
Console.WriteLine("Press enter to continue"); | |
Console.ReadLine(); | |
Directory.CreateDirectory(path); | |
} | |
else | |
{ | |
Directory.CreateDirectory(path); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment