Created
May 16, 2025 08:07
-
-
Save tored/eaddb2a048fda2cc6954d5c167dd0073 to your computer and use it in GitHub Desktop.
Git clean merged branches locally and optionally remote
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env php | |
<?php | |
/** | |
* Git cleanup script: deletes merged branches locally (and optionally on remote). | |
* | |
* Usage: | |
* php git-clean-merged.php [--with-remote] [--help] | |
* | |
* Options: | |
* --with-remote Also delete branches on origin | |
* --help Show this help message | |
* | |
* Default behavior is to delete only local merged branches. | |
*/ | |
// Parse command-line options | |
$options = getopt('', ['with-remote', 'help']); | |
if (isset($options['help'])) { | |
echo <<<EOT | |
Usage: php git-clean-merged.php [options] | |
Options: | |
--with-remote Also delete branches on the remote (origin) | |
--help Show this help text | |
This script removes all local branches that have been merged into the default branch. | |
Use --with-remote to also delete them from the remote repository (origin). | |
After cleanup, it switches back to the branch you started from. | |
EOT; | |
exit(0); | |
} | |
// Check if we're in a Git repository | |
if (!is_dir('.git') && shell_exec('git rev-parse --git-dir 2>/dev/null') === null) { | |
echo "Error: Not inside a Git repository.\n"; | |
exit(1); | |
} | |
// Save current branch | |
$currentBranch = trim(shell_exec("git rev-parse --abbrev-ref HEAD")); | |
if (!$currentBranch) { | |
echo "Error: Unable to determine current branch.\n"; | |
exit(1); | |
} | |
// Determine default (base) branch | |
$rawBaseBranch = shell_exec("git symbolic-ref refs/remotes/origin/HEAD 2>&1"); | |
if (!$rawBaseBranch) { | |
echo "Error: Failed to determine the base branch. Make sure origin/HEAD is set.\n"; | |
exit(1); | |
} | |
$baseBranch = trim(str_replace('refs/remotes/origin/', '', $rawBaseBranch)); | |
echo "Default branch detected: $baseBranch\n"; | |
// Switch to base branch | |
echo "Switching to $baseBranch...\n"; | |
shell_exec("git checkout $baseBranch 2>&1"); | |
// Fetch and prune remote branches | |
echo "Running git fetch --prune...\n"; | |
shell_exec("git fetch --prune 2>&1"); | |
// Find merged local branches | |
echo "Finding merged local branches...\n"; | |
$mergedBranches = shell_exec("git branch --merged"); | |
if (!$mergedBranches) { | |
echo "No merged branches found or an error occurred.\n"; | |
shell_exec("git checkout $currentBranch 2>&1"); | |
exit(1); | |
} | |
foreach (explode("\n", trim($mergedBranches)) as $branchLine) { | |
$branchLine = trim($branchLine); | |
if ($branchLine === '') continue; | |
if (strpos($branchLine, '*') === 0) { | |
$branchLine = ltrim($branchLine, '* '); | |
} | |
if ($branchLine === $baseBranch) continue; | |
echo "Deleting local branch '$branchLine'...\n"; | |
shell_exec("git branch -d $branchLine 2>&1"); | |
if (isset($options['with-remote'])) { | |
echo "Deleting remote branch '$branchLine' from origin...\n"; | |
shell_exec("git push origin --delete $branchLine 2>&1"); | |
} | |
} | |
// Switch back to original branch | |
if ($currentBranch !== $baseBranch) { | |
echo "Returning to original branch '$currentBranch'...\n"; | |
shell_exec("git checkout $currentBranch 2>&1"); | |
} | |
echo "Cleanup complete.\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment