Skip to content

Switching Branches

polyrepo switch-default (alias sd) — pick repos and switch each to its up-to-date default branch.

bash
polyrepo switch-default [options]

Each repo's default branch is detected per repo, not assumed — GitHub itself defaults a new repo to main, and plenty of people rename it (master included), so a mixed folder of repos can easily have some on master and some on main. Detection prefers the locally cached origin/HEAD ref (no network — set by git clone), falls back to asking origin directly (read-only), then to whichever of master/main exists as a local branch, and finally to main (GitHub's own default) if nothing else could tell it.

  1. Shows a checkbox list of every repo with its current branch (and its default branch, when the two differ); repos not currently on their default branch are pre-selected.
  2. After confirming, for each selected repo, one at a time: a dirty working tree is skipped with a warning, untouched; otherwise git fetch origingit checkout <default branch>git merge --ff-only origin/<default branch>.
  3. If the local default branch has diverged from origin (fast-forward isn't possible), that repo is reported and left alone to resolve by hand.

Options

--packages <a,b,c>

Package list instead of the interactive checkbox.

--yes

Skip the "proceed?" confirmation.

--force

Changes steps 2 and 3 above: a dirty working tree is no longer skipped, and each repo gets git checkout -f <default branch> + git reset --hard origin/<default branch> instead of the safe fast-forward-only merge — uncommitted changes to tracked files and any local-only commits on that branch are permanently discarded. Untracked files are still left alone at this point (this isn't git clean). The checkbox marks which selected repos would lose changes, and the proceed confirmation says how many and defaults to "No" instead of "Yes" whenever --force would actually discard something.

--clean

With --force, also runs git clean -fd — removes untracked files/directories that aren't gitignored (build output that isn't in .gitignore is the common case). Gitignored paths like node_modules are still left alone; -x is deliberately not used. Only means anything alongside --force — without it there's nothing to discard in the first place.

Example output--force on a repo with an uncommitted edit to package.json:

[1/1] vue-toast-kit
  $ git fetch origin
  $ git checkout -f master
    Your branch is up to date with 'origin/master'.
    Already on 'master'
  $ git reset --hard origin/master
    HEAD is now at 775ac80 init
  ✓ Discarded local changes — now on master, matching origin.

Example:

bash
polyrepo switch-default

# discard local changes on a repo you don't need anymore
polyrepo switch-default --packages vue-toast-kit --force

# same, but also wipe untracked build output etc.
polyrepo switch-default --packages vue-toast-kit --force --clean