Skip to content

Instantly share code, notes, and snippets.

@dirq
Last active September 16, 2025 19:55
Show Gist options
  • Save dirq/05903577e18ebb40b37f60a9a9b2b083 to your computer and use it in GitHub Desktop.
Save dirq/05903577e18ebb40b37f60a9a9b2b083 to your computer and use it in GitHub Desktop.
Clean up old local Git branches with smart archiving - renames old/merged branches with "old/" prefix instead of deleting them.
# Rename old local git branches script
#
# This script renames local git branches as follows:
# - Branches not 'main', 'master', or the current branch
# - Branches not already starting with 'old/' and not ending with 'release'
# - If the branch has not had a commit in over the specified days, it is renamed to 'old/{branch}'
# - If the branch has been merged into 'eagleeye-prod-release' or 'eagleeye-stage-release', it is renamed to 'old/merged/{branch}'
#
# Usage:
# .\rename-old-local-git-branches.ps1 -FolderPath <path-to-git-repo> -DaysOld <days> [-DryRun]
# -FolderPath: Path to the git repository (optional, defaults to current directory)
# -DaysOld: Number of days since last commit to consider a branch old (optional, defaults to 30)
# -DryRun: If specified, only print what would be renamed, do not actually rename branches
param(
[string]$FolderPath = (Get-Location),
[int]$DaysOld = 30,
[switch]$DryRun
)
Set-Location -Path $FolderPath
Write-Host "πŸ”„ Fetching latest branch info..." -ForegroundColor Cyan
git fetch --prune 2>$null | Out-Null
Write-Host "βœ… Fetch complete!" -ForegroundColor Green
$now = Get-Date
$thresholdDate = $now.AddDays(-$DaysOld)
$thresholdUnix = [int][double]::Parse($thresholdDate.ToUniversalTime().Subtract([datetime]'1970-01-01').TotalSeconds)
if ($DryRun)
{
Write-Host "πŸ§ͺ DRY RUN: No branches will be renamed." -ForegroundColor Magenta
}
$currentBranch = git branch --show-current
$branches = git branch --format="%(refname:short)" | Where-Object {
$_ -notin @("main", "master") `
-and $_ -ne $currentBranch `
-and -not $_.StartsWith("old/") `
-and -not $_.ToLower().EndsWith("release")
}
$mergedIntoProd = git branch --merged eagleeye-prod-release | ForEach-Object { $_.Trim() }
$mergedIntoStage = git branch --merged eagleeye-stage-release | ForEach-Object { $_.Trim() }
$mergedBranches = ($mergedIntoProd + $mergedIntoStage) | Select-Object -Unique
Write-Host ("🌿 Current branch: {0}`n⏰ Using threshold of {1} days ({2})" -f $currentBranch, $DaysOld, $thresholdDate) -ForegroundColor Magenta
foreach ($branch in $branches) {
$lastCommitUnix = git log -1 --format="%ct" $branch 2>$null
$isMerged = $mergedBranches -contains $branch
$isOld = $false
$lastCommitDate = "N/A"
# Parse commit timestamp safely
if (![string]::IsNullOrWhiteSpace($lastCommitUnix) -and $lastCommitUnix.Trim() -ne "") {
try {
$commitUnixNum = [long]$lastCommitUnix.Trim()
if ($commitUnixNum -gt 0) {
# Convert Unix timestamp to DateTime using .NET method
$epoch = [datetime]::new(1970, 1, 1, 0, 0, 0, [DateTimeKind]::Utc)
$lastCommitDate = $epoch.AddSeconds($commitUnixNum).ToLocalTime()
$isOld = $commitUnixNum -lt $thresholdUnix
# Write-Host "DEBUG: Branch '$branch' - Unix: $commitUnixNum, Date: $lastCommitDate, IsOld: $isOld, Threshold: $thresholdUnix" -ForegroundColor Cyan
}
}
catch [System.Exception] {
# If parsing fails, keep defaults (N/A date, not old)
Write-Host "❌ ERROR parsing timestamp '$lastCommitUnix' for branch '$branch': $($_.Exception.Message)" -ForegroundColor Red
$lastCommitDate = "N/A"
$isOld = $false
}
} else {
Write-Host "πŸ” DEBUG: No commit timestamp found for branch '$branch'" -ForegroundColor Red
}
if ($isMerged) {
$newBranch = "old/merged/$branch"
Write-Host "πŸ“¦ [ARCHIVE MERGED] $branch -> $newBranch (last commit: $lastCommitDate, merged: $isMerged)" -ForegroundColor Yellow
if (-not $DryRun) {
git branch -m $branch $newBranch
}
} elseif ($isOld) {
$newBranch = "old/$branch"
Write-Host "πŸ—„οΈ [ARCHIVE OLD] $branch -> $newBranch (last commit: $lastCommitDate, merged: $isMerged)" -ForegroundColor Yellow
if (-not $DryRun) {
git branch -m $branch $newBranch
}
} else {
Write-Host "⏭️ [skip] $branch (last commit: $lastCommitDate, merged: $isMerged)" -ForegroundColor DarkGray
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment