Skip to content

Instantly share code, notes, and snippets.

@GottZ
Created January 16, 2026 18:30
Show Gist options
  • Select an option

  • Save GottZ/ce41628c75c74617be9703d34679f5c3 to your computer and use it in GitHub Desktop.

Select an option

Save GottZ/ce41628c75c74617be9703d34679f5c3 to your computer and use it in GitHub Desktop.
yolopull & yolopush

Git YOLO Aliases

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.

Installation

# 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'

Commands

git yolopull <frombranch> [remotes...]

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)

Usage

# On main branch, merge feature-branch into main
git checkout main
git yolopull feature-branch

# Specify remotes explicitly
git yolopull feature-branch origin upstream

git yolopush <targetbranch> [remotes...]

Merge 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

Usage

# On feature-branch, merge into main
git checkout feature-branch
git yolopush main

# Specify remotes explicitly
git yolopush main origin upstream

Special Behavior

If 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

Comparison

Aspect yolopull yolopush
You are on Target branch Source branch
Argument Source branch to merge Target branch to merge into
Merge direction argcurrent currentarg
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

Remote Selection

Both commands support flexible remote selection for branch deletion.

Automatic Selection

Scenario Behavior
No remotes configured Skips remote operations
Single remote Automatically selected
Multiple remotes Interactive prompt (if no args)

Explicit Remotes

Pass remote names as additional arguments:

git yolopull feature-branch origin upstream fork
git yolopush main origin backup

Interactive Selection

When 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

Workflow

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!                               │
└─────────────────────────────────────────────────────────────┘

Error Handling

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)

Examples

Typical Feature Branch Workflow

# 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

Pulling a Hotfix

# 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

Creating a Release Branch

# 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)

Multi-Remote Setup

# 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 upstream

Uninstallation

git config --global --unset alias.yolopull
git config --global --unset alias.yolopush

License

MIT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment