src/Split-GitHistory.ps1
#!/usr/bin/env pwsh $ErrorActionPreference = "Stop" Set-StrictMode -Version Latest # Adapted from: https://stackoverflow.com/a/44036771/12553250 function Split-GitHistory { [CmdletBinding()] param( [Parameter(Position = 0, Mandatory = $true)] [ValidateScript({Test-Path $_ })] [string] $source, [Parameter(Position = 1, Mandatory = $true)] [string[]] $destination ) Begin { $ErrorActionPreference = "Stop" } Process { [string] $currentOperation [string[]] $commitsToMerge = @() [int] $opNumberMax = 3 + $destination.Length [int] $opNumber = 1 $currentOperation = "♻🖇 Git History Split ($opNumber/$opNumberMax): 📎 Sidelines Original File" Write-Progress -Activity "Splitting Git History of File" -CurrentOperation $currentOperation [string] $sourceCopy = $source + "-" + $(git rev-parse HEAD) git mv $source $sourceCopy git commit -m $currentOperation $commitsToMerge += $(git rev-parse HEAD) git reset --hard HEAD^ [int] $destinationNumber = 1 foreach ($singleDestination in $destination) { $opNumber += 1 $currentOperation = "♻🖇 Git History Split ($opNumber/$opNumberMax): 🔤 Renames Original File to Destination $destinationNumber of $($destination.Length)" Write-Progress -Activity "Splitting Git History of File" -CurrentOperation $currentOperation git mv $source $destination git commit -m $currentOperation $commitsToMerge += $(git rev-parse HEAD) git reset --hard HEAD^ $destinationNumber += 1 } $opNumber += 1 $currentOperation = "♻🖇 Git History Split ($opNumber/$opNumberMax): 🔀 Merges Divergent Commits" Write-Progress -Activity "Splitting Git History of File" -CurrentOperation $currentOperation [string] $mergeStartCommit = $commitsToMerge | select -first 1 [string[]] $remainingCommitsToMerge = $commitsToMerge | select -skip 1 git reset --hard $mergeStartCommit git merge @remainingCommitsToMerge # This will generate conflicts git commit -a -m $currentOperation # Trivially resolve conflicts like this $opNumber += 1 $currentOperation = "♻🖇 Git History Split ($opNumber/$opNumberMax): ◀ Restores Original File" Write-Progress -Activity "Splitting Git History of File" -CurrentOperation $currentOperation git mv $sourceCopy $source git commit -m $currentOperation Write-Progress -Activity "Splitting Git History of File" -Completed } } |