Aggressive git workflow aliases for merging and cleaning up branches with automatic stash handling, multi-remote support, and branch cleanup.
⚠️ Warning: These commands delete branches locally and remotely. Use with caution.
# Install yolopull
git config --global alias.yolopull '!f() { \
if [ -z "$1" ]; then echo "Usage: git yolopull <frombranch> [remotes...]"; return 1; fi; \
branch="$1"; shift; \
current=$(git rev-parse --abbrev-ref HEAD); \
if [ "$branch" = "$current" ]; then echo "Error: Cannot merge branch into itself"; return 1; fi; \
all_remotes=$(git remote); \
remote_count=$(echo "$all_remotes" | wc -l); \
if [ $# -gt 0 ]; then \
remotes="$*"; \
elif [ "$remote_count" -gt 1 ]; then \
echo "Multiple remotes found:"; \
i=1; echo "$all_remotes" | while read r; do echo " $i) $r"; i=$((i+1)); done; \
printf "Select remotes (e.g. 1-3,5) or enter to skip: "; \
read selection; \
if [ -n "$selection" ]; then \
remotes=$(echo "$selection" | tr "," "\n" | while read part; do \
if echo "$part" | grep -q "-"; then \
start=$(echo "$part" | cut -d"-" -f1); \
end=$(echo "$part" | cut -d"-" -f2); \
seq "$start" "$end"; \
else \
echo "$part"; \
fi; \
done | while read num; do echo "$all_remotes" | sed -n "${num}p"; done | tr "\n" " "); \
else \
remotes=""; \
fi; \
elif [ "$remote_count" -eq 1 ]; then \
remotes="$all_remotes"; \
else \
remotes=""; \
fi; \
stashed=0; \
if git merge "$branch" 2>/dev/null; then \
echo "Merge successful"; \
else \
echo "Merge failed, stashing changes..."; \
git merge --abort 2>/dev/null; \
stash_result=$(git stash push -m "yolopull-auto-stash"); \
if echo "$stash_result" | grep -q "No local changes"; then \
echo "Error: Merge failed and no changes to stash"; return 1; \
fi; \
stashed=1; \
if ! git merge "$branch"; then \
echo "Error: Merge still fails after stashing"; \
git merge --abort 2>/dev/null; \
git stash pop; \
return 1; \
fi; \
echo "Merge successful after stashing, popping stash..."; \
if ! git stash pop; then \
echo "Error: Stash pop failed, reverting merge"; \
git reset --hard HEAD~1; \
git stash pop 2>/dev/null; \
return 1; \
fi; \
fi; \
echo "Deleting $branch locally..."; \
git branch -d "$branch" 2>/dev/null || git branch -D "$branch"; \
for remote in $remotes; do \
if git ls-remote --exit-code --heads "$remote" "$branch" >/dev/null 2>&1; then \
echo "Deleting $branch from $remote..."; \
git push "$remote" --delete "$branch"; \
fi; \
done; \
git fetch --prune; \
echo "Done!"; \
}; f'
# Install yolopush
git config --global alias.yolopush '!f() { \
if [ -z "$1" ]; then echo "Usage: git yolopush <targetbranch> [remotes...]"; return 1; fi; \
target="$1"; shift; \
frombranch=$(git rev-parse --abbrev-ref HEAD); \
if [ "$target" = "$frombranch" ]; then echo "Error: Already on target branch"; return 1; fi; \
all_remotes=$(git remote); \
remote_count=$(echo "$all_remotes" | wc -l); \
if [ $# -gt 0 ]; then \
remotes="$*"; \
elif [ "$remote_count" -gt 1 ]; then \
echo "Multiple remotes found:"; \
i=1; echo "$all_remotes" | while read r; do echo " $i) $r"; i=$((i+1)); done; \
printf "Select remotes (e.g. 1-3,5) or enter to skip: "; \
read selection; \
if [ -n "$selection" ]; then \
remotes=$(echo "$selection" | tr "," "\n" | while read part; do \
if echo "$part" | grep -q "-"; then \
start=$(echo "$part" | cut -d"-" -f1); \
end=$(echo "$part" | cut -d"-" -f2); \
seq "$start" "$end"; \
else \
echo "$part"; \
fi; \
done | while read num; do echo "$all_remotes" | sed -n "${num}p"; done | tr "\n" " "); \
else \
remotes=""; \
fi; \
elif [ "$remote_count" -eq 1 ]; then \
remotes="$all_remotes"; \
else \
remotes=""; \
fi; \
if ! git rev-parse --verify "$target" >/dev/null 2>&1; then \
echo "Target branch does not exist, renaming $frombranch to $target..."; \
git branch -m "$frombranch" "$target"; \
for remote in $remotes; do \
if git ls-remote --exit-code --heads "$remote" "$frombranch" >/dev/null 2>&1; then \
echo "Updating $remote: deleting old, pushing new..."; \
git push "$remote" --delete "$frombranch"; \
git push -u "$remote" "$target"; \
fi; \
done; \
git fetch --prune; \
echo "Done!"; \
return 0; \
fi; \
stashed=0; \
stash_result=$(git stash push -m "yolopush-auto-stash"); \
if ! echo "$stash_result" | grep -q "No local changes"; then \
stashed=1; \
echo "Stashed local changes"; \
fi; \
git checkout "$target"; \
if git merge "$frombranch" 2>/dev/null; then \
echo "Merge successful"; \
else \
echo "Merge failed, aborting..."; \
git merge --abort 2>/dev/null; \
git checkout "$frombranch"; \
if [ $stashed -eq 1 ]; then git stash pop; fi; \
return 1; \
fi; \
if [ $stashed -eq 1 ]; then \
echo "Popping stash..."; \
if ! git stash pop; then \
echo "Error: Stash pop failed, reverting merge"; \
git reset --hard HEAD~1; \
git checkout "$frombranch"; \
git stash pop 2>/dev/null; \
return 1; \
fi; \
fi; \
echo "Deleting $frombranch locally..."; \
git branch -d "$frombranch" 2>/dev/null || git branch -D "$frombranch"; \
for remote in $remotes; do \
if git ls-remote --exit-code --heads "$remote" "$frombranch" >/dev/null 2>&1; then \
echo "Deleting $frombranch from $remote..."; \
git push "$remote" --delete "$frombranch"; \
fi; \
done; \
git fetch --prune; \
echo "Done!"; \
}; f'Merge a branch into your current branch, then delete it.
You are on the target branch, pulling changes from another branch.
feature-branch ──┐
▼
main (you are here)
# On main branch, merge feature-branch into main
git checkout main
git yolopull feature-branch
# Specify remotes explicitly
git yolopull feature-branch origin upstreamMerge your current branch into a target branch, then delete your current branch.
You are on the feature branch, pushing changes to another branch.
feature-branch (you are here)
│
▼
main
# On feature-branch, merge into main
git checkout feature-branch
git yolopush main
# Specify remotes explicitly
git yolopush main origin upstreamIf the target branch does not exist, yolopush will rename your current branch to the target branch (locally and on selected remotes) instead of merging.
# On feature-branch, but 'release-v2' doesn't exist
git yolopush release-v2
# Result: feature-branch is renamed to release-v2| Aspect | yolopull |
yolopush |
|---|---|---|
| You are on | Target branch | Source branch |
| Argument | Source branch to merge | Target branch to merge into |
| Merge direction | arg → current |
current → arg |
| Branch deleted | Argument branch | Current branch |
| After success | Stay on current branch | End up on target branch |
| Rename behavior | — | Renames if target doesn't exist |
Both commands support flexible remote selection for branch deletion.
| Scenario | Behavior |
|---|---|
| No remotes configured | Skips remote operations |
| Single remote | Automatically selected |
| Multiple remotes | Interactive prompt (if no args) |
Pass remote names as additional arguments:
git yolopull feature-branch origin upstream fork
git yolopush main origin backupWhen multiple remotes exist and none are specified, you'll see an interactive prompt:
Multiple remotes found:
1) origin
2) upstream
3) fork
4) backup
Select remotes (e.g. 1-3,5) or enter to skip: _
Selection syntax:
| Input | Selected |
|---|---|
1 |
origin |
1,3 |
origin, fork |
1-3 |
origin, upstream, fork |
1-2,4 |
origin, upstream, backup |
| (empty) | Skip remote deletion |
Both commands follow similar error-handling logic:
┌─────────────────────────────────────────────────────────────┐
│ Start │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Try merge │
└─────────────────────────────────────────────────────────────┘
│
┌────────────┴────────────┐
│ │
Success Fail
│ │
│ ▼
│ ┌───────────────────────────────┐
│ │ Abort merge, stash changes │
│ └───────────────────────────────┘
│ │
│ ▼
│ ┌───────────────────────────────┐
│ │ Try merge again │
│ └───────────────────────────────┘
│ │
│ ┌────────────┴────────────┐
│ │ │
│ Success Fail
│ │ │
│ ▼ ▼
│ ┌──────────────┐ ┌────────────────────────┐
│ │ Pop stash │ │ Unstash, report error │
│ └──────────────┘ │ EXIT │
│ │ └────────────────────────┘
│ │
│ ┌────────┴────────┐
│ │ │
│ Success Fail
│ │ │
│ │ ▼
│ │ ┌────────────────────────────┐
│ │ │ Revert merge, restore │
│ │ │ stash, EXIT │
│ │ └────────────────────────────┘
│ │
└───┴───────────┐
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Delete branch locally │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Delete branch from selected remotes (if exists) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ git fetch --prune │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Done! │
└─────────────────────────────────────────────────────────────┘
Both commands are designed to leave your repository in a clean state on failure:
| Failure Point | Recovery Action |
|---|---|
| Initial merge fails | Stash changes, retry |
| Merge fails after stash | Abort merge, restore stash, exit |
| Stash pop fails | Revert merge (reset --hard), restore stash, exit |
| Remote deletion fails | Continue (non-fatal) |
# Create and work on feature
git checkout -b feature/awesome-thing
# ... make commits ...
# Ready to merge into main
git yolopush main
# Result:
# - main now contains feature/awesome-thing commits
# - feature/awesome-thing deleted locally and from origin
# - You're now on main# On main, pull in a hotfix branch
git checkout main
git yolopull hotfix/critical-bug
# Result:
# - main now contains the hotfix
# - hotfix/critical-bug deleted locally and from origin
# - You're still on main# On develop, create a release (target doesn't exist)
git checkout develop
git yolopush release/v2.0
# Result:
# - develop renamed to release/v2.0
# - Remote updated (old branch deleted, new branch pushed)# You have: origin (GitHub), upstream (main repo), fork (your fork)
git yolopull feature-branch origin fork
# Deletes feature-branch from origin and fork, but not upstreamgit config --global --unset alias.yolopull
git config --global --unset alias.yolopushMIT