') + ')', 'gi');
if (regex.test(text)) {
found = true;
var frag = document.createDocumentFragment();
var parts = text.split(regex);
parts.forEach(function(part, i) {
if (i % 2 === 0) {
frag.appendChild(document.createTextNode(part));
} else {
var span = document.createElement('span');
span.className = 'userscript-highlight';
span.textContent = part;
frag.appendChild(span);
}
});
node.parentNode.replaceChild(frag, node);
}
});
} else if (node.nodeType === 1 && node.childNodes) { // element
var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];
if (!skipTags.includes(node.tagName)) {
Array.from(node.childNodes).forEach(highlight);
}
}
}
highlight(document.body);
// Re-highlight on dynamic content
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
m.addedNodes.forEach(function(node) {
if (node.nodeType === 1 || node.nodeType === 3) highlight(node);
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); }
})();
(function(){
try {
var __m = "*";
var __re = new RegExp('^' + ".*" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Strip utm_, fbclid, gclid, etc. from all links on page
(function() {
var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',
'ref', 'ref_src', 'source', 'medium', 'campaign'];
function cleanUrl(url) {
try {
var u = new URL(url, window.location.origin);
var changed = false;
trackingParams.forEach(function(p) {
if (u.searchParams.has(p)) {
u.searchParams.delete(p);
changed = true;
}
});
return changed ? u.toString() : url;
} catch (e) {
return url;
}
}
function cleanLinks() {
document.querySelectorAll('a[href]').forEach(function(a) {
var clean = cleanUrl(a.href);
if (clean !== a.href) a.href = clean;
});
}
cleanLinks();
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
m.addedNodes.forEach(function(node) {
if (node.nodeType === 1) {
if (node.tagName === 'A') cleanLinks();
node.querySelectorAll('a[href]').forEach(function(a) {
var clean = cleanUrl(a.href);
if (clean !== a.href) a.href = clean;
});
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); }
})();
(function(){
try {
var __m = "youtube.com";
var __re = new RegExp('^' + "youtube\\.com" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Auto-enable theater mode on YouTube
(function() {
function tryTheater() {
var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]');
if (btn && !btn.classList.contains('activated')) {
btn.click();
}
}
// Try immediately
tryTheater();
// Try after navigation (SPA)
var lastUrl = location.href;
setInterval(function() {
if (location.href !== lastUrl) {
lastUrl = location.href;
setTimeout(tryTheater, 500);
}
}, 1000);
// Also try on player load
var observer = new MutationObserver(tryTheater);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); }
})();
(function(){
try {
var __m = "*";
var __re = new RegExp('^' + ".*" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Remove or un-stick sticky/fixed headers that block content
(function() {
function unstick() {
document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) {
if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {
el.style.position = 'static';
el.style.top = 'auto';
el.style.zIndex = 'auto';
}
});
}
unstick();
var observer = new MutationObserver(unstick);
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
})();
}
} catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); }
})();
})();
GitHub - Wian47/git-clean: A terminal utility to scan local Git branches, inspect their merged status & commit age, and batch-clean stale branches interactively. · GitHub
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Interactive Git Branch Janitor
A terminal utility to scan local Git branches, inspect their merged status & commit age, and batch-clean stale branches interactively.
🌐 Remote Branch Cleanup (--remote): Delete remote tracking branches on origin alongside local branches.
🔍 Live Commit Inspector (--preview): Render dynamic commit log preview trees detailing recent commits and authors for candidate branches before deleting.
🔒 Protected Branch Guards: Built-in protection for main, master, dev, staging, production, and custom patterns (--protect). Protected branches cannot be accidentally selected or deleted.
↺ Branch Recovery (--undo): Automatic session history logging to .git/git_clean_history.json. Deleted branches can be restored anytime with git-clean --undo.
👤 Author Filtering (--only-mine): Filter branches authored by the active git user (user.name/user.email).
⚡ Remote Pruning (--prune): Auto-prune stale remote tracking refs (git fetch --prune) prior to scanning.
Smart Filtering: Filter by branch age (--older-than 30d), merge state (--merged-only, --unmerged-only), or non-interactive mode (-y).
uv tool install git+https://github.com/Wian47/git-clean.git
# Or run instantly without installing:
uvx --from git+https://github.com/Wian47/git-clean.git git-clean
Option 3: pipx or pip
pipx install git+https://github.com/Wian47/git-clean.git
# Or install locally via pip:
pip install -e .
⚙️ Command Options
usage: git_clean.py [-h] [--path PATH] [--target TARGET] [--force] [--dry-run]
[--undo] [--protect [PROTECT ...]] [--older-than OLDER_THAN]
[--merged-only] [--unmerged-only] [--only-mine] [--remote]
[--prune] [--preview] [--non-interactive]
Interactive Git Branch Cleanup Utility
options:
-h, --help Show this help message and exit
--path, -p PATH Path to Git repository (default: current directory)
--target, -t TARGET Target branch to check merge status against (default: auto-detect main/master)
--force, -f Force delete unmerged branches (uses git branch -D)
--dry-run Simulate deletion without actually removing branches
--undo Restore branches deleted in the previous git-clean session
--protect [PAT ...] Additional branch patterns to protect from deletion
--older-than DURATION Only filter branches with last commit older than duration (e.g. 30d, 2w, 6m)
--merged-only Only candidate merged/squashed/gone branches
--unmerged-only Only candidate unmerged branches
--only-mine Only filter branches authored by current git user
--remote, -r Also delete remote tracking branches on origin
--prune, -P Run 'git fetch --prune' before scanning
--preview Display commit log preview inspector before prompt
--non-interactive, -y Auto-confirm branch deletion