top of page
Search

Cleaning up master → main without creating a mess you have to clean up later

  • Writer: Shannon
    Shannon
  • May 8
  • 6 min read

At some point you look across your repos and realize you've got some sort of split personality problem. Half your projects are on main, the other half are still on master, and every time you touch a pipeline, clone a repo, or write documentation, you have to stop and remember which one you're dealing with. You know it's not broken, it's just inconsistent enough to be a persistent low-grade annoyance. I recently went through this myself and thought about adding this to my blog as a way to help any of you out if you have repos that still have "master".


Now, the instinct is to fix it all very quickly. Rename the branch, move on, and you're done. The reality is that the rename is the least interesting part of this effort. What matters is everything that quietly depends on that branch name, and that's what turns a quick cleanup into something that breaks builds and deployments in ways that aren't immediately obvious.


So instead of starting with the rename, start by figuring out what still thinks master exists. You may thank me later!


Start by figuring out what depends on master

Before you touch anything, take a few minutes to surface where master is actually being used. Over time it creeps into pipeline triggers, Terraform modules, scripts, and external systems that pull from your repo. Keep in mind, you're not trying to fix everything yet. You're trying to answer one question: what breaks if I remove master?


Do a quick sweep of the repo

The easiest place to start is the repo itself:

git grep -n "master"

That command gives you every tracked file where master appears. From there you can scan for actual dependencies rather than comments or docs. If you want to be more targeted about catching real branch references, use this command:

git grep -nE "origin/master|refs/heads/master|ref=master|master"

For a broader sweep that includes untracked files and skips common noise, use this command:

grep -RIn --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=.terraform "master" .

I've found that usually catches a few things git grep misses.


Spend Some extra time on pipelines

If something is going to break after the switch, it's almost always here...your pipelines! Pipelines are explicit about branch names and they don't adapt unless you tell them to.

Look through your workflow and pipeline definitions (GitHub Actions, Azure DevOps, Jenkins, whatever you're running) for triggers and conditions tied to master:

yaml trigger

on:
  push:
    branches:
      - master

yaml condition

if: github.ref == 'refs/heads/master'

These unfortunately won't fix themselves. If your deployment pipeline is tied to master and you remove it, nothing runs. Your pipelines quietly stop doing what you expected.

Here's an example of a focused scan for GitHub Actions:

grep -RIn "master" .github/workflows

That alone usually finds the majority of pipeline-level dependencies.


Don't forget GitHub settings

Some dependencies aren't in code at all. They're in repo settings, which makes them easy to overlook. Before switching anything, check the:


  • Default branch

  • Branch protection rules and required status checks

  • PR policies and rulesets

  • Environment and deployment restrictions


GitHub does a decent job helping with renames, but it's not aware of your intent (if only!). If protections are tied to master, you want to know that before making changes so you can confirm everything moves cleanly.


Think beyond GitHub

This is where things get missed. Anything outside GitHub that interacts with your repo could still be referencing master. Reviewing and identifying components such as Azure DevOps pipelines, Jenkins jobs, ArgoCD configurations, Terraform modules, or scripts that interact with or clone your repository will help you completely squash the issue before it's an issue.

Here's a common example in Terraform:

source = "git::https://github.com/yourorg/yourrepo.git?ref=master"

That won't throw an obvious error right away. It'll just start behaving in ways that don't make sense once master is gone. I will mention this too: you don't need to audit every system in your environment, but you should think through what's pulling from your repos and whether it assumes master.


Use a script to speed this up

If you want something reusable, this gives you a solid first pass:

#!/usr/bin/env bash

echo "Searching tracked files for references to master..."
git grep -nE "origin/master|refs/heads/master|ref=master|master" || true

echo ""
echo "Checking GitHub Actions workflows..."
if [ -d ".github/workflows" ]; then
  grep -RIn "master" .github/workflows || true
else
  echo "No GitHub Actions workflows directory found."
fi

echo ""
echo "Checking common pipeline and IaC files..."
find . \( -name "*.yml" -o -name "*.yaml" -o -name "*.tf" -o -name "Jenkinsfile" -o -name "*.sh" \) \
  -not -path "*/.git/*" \
  -not -path "*/node_modules/*" \
  -not -path "*/.terraform/*" \
  -print0 | xargs -0 grep -In "master" 2>/dev/null || true

echo ""
echo "Done. Review anything referencing master before switching branches."

Run it once, skim the output, and you'll have a clear picture of what needs attention before you touch anything. This script could save you hours upfront!

Once you understand the dependencies, the switch is straightforward

At this point you know what depends on master, or at least where to look if something behaves unexpectedly. That makes the actual switch uneventful (and remember, from past blogs, I like uneventful changes).


Rename the branch

You can do this directly in GitHub (simplest path) or locally if you want something scriptable:

git branch -m master main
git push -u origin main

Now both branches coexist briefly while you validate things.


Change the default branch

Go to Settings → Branches and flip the default branch to main. This is what actually changes how the repo behaves going forward. New pull requests, merges, and most integrations will start using main.


Give yourself a short validation window

Before deleting master, run a build, trigger a deployment, confirm nothing obvious is broken. Having both branches temporarily gives you a safety net without any real cost.

Remove master

Once you're confident everything is clean:

git push origin --delete master

Update local clones

Anyone who cloned the repo will still be on master locally. That doesn't fix itself, so share these commands with your team:

git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a

Skipping this step generates a lot of small, annoying issues.


Doing this at scale with the GitHub CLI

For a handful of repos, the manual approach is fine. For dozens or hundreds, it gets old fast. The key idea is to script against your repos rather than clicking through them while still respecting the same rule: don't flip anything until you know it's ready.


Get visibility before you change anything

Run this first. It doesn't modify anything. It just shows you the state of each repo.

ORG="YOUR_ORG"

gh repo list "$ORG" --limit 1000 --json nameWithOwner -q '.[].nameWithOwner' | while read -r REPO; do
  DEFAULT_BRANCH=$(gh api "repos/$REPO" --jq '.default_branch')

  gh api "repos/$REPO/branches/main" >/dev/null 2>&1 && MAIN_STATUS="yes" || MAIN_STATUS="no"
  gh api "repos/$REPO/branches/master" >/dev/null 2>&1 && MASTER_STATUS="yes" || MASTER_STATUS="no"

  echo "$REPO | default=$DEFAULT_BRANCH | has_main=$MAIN_STATUS | has_master=$MASTER_STATUS"
done

This gives you a snapshot of which repos are ready, which still only have master, and which are already cleaned up.


Switch repos that already have main

Once you know which ones are ready, flip the default branch for those:

ORG="YOUR_ORG"

gh repo list "$ORG" --limit 1000 --json nameWithOwner -q '.[].nameWithOwner' | while read -r REPO; do
  if gh api "repos/$REPO/branches/main" >/dev/null 2>&1; then
    echo "Switching $REPO to main..."
    gh repo edit "$REPO" --default-branch main
  else
    echo "Skipping $REPO (no main branch)"
  fi
done

Rename master to main via API

If you want to do everything from GitHub without cloning repos locally:

ORG="YOUR_ORG"

gh repo list "$ORG" --limit 1000 --json nameWithOwner -q '.[].nameWithOwner' | while read -r REPO; do
  if gh api "repos/$REPO/branches/main" >/dev/null 2>&1; then
    echo "$REPO already has main"
  elif gh api "repos/$REPO/branches/master" >/dev/null 2>&1; then
    echo "Renaming master to main for $REPO..."
    gh api \
      --method POST \
      "repos/$REPO/branches/master/rename" \
      -f new_name='main'

    sleep 3
    gh repo edit "$REPO" --default-branch main
  else
    echo "Skipping $REPO (no master or main)"
  fi
done

That's the closest thing to full automation without touching local clones.


The way to think about All of this

This isn't really a branch rename, rather it's a cleanup of accumulated assumptions and a little bit of that tribal knowledge. The branch name just happens to be the thing exposing everything like an eye sore. In all my discussions with customers, I've realized tribal knowledge is directly linked to technical debt. Let's clean that up and quickly.


If you spend a little time on dependencies first, the switch itself becomes boring. Skip that step and you'll still get there (probably), but you'll do it while troubleshooting things that quietly stopped working. My recommendation: do it once, do it cleanly, and you won't ever have to think about it again...at least in theory!

2 Comments


Steven Burgees
Steven Burgees
May 20

This post explains software cleanup and version control in a very practical way, especially how poor planning can create future technical problems. While studying software engineering concepts, I struggled with structuring workflows and wanted help with assignment to understand how clean system design works. It shows that careful planning in development prevents confusion and saves time in later stages of a project. nice post

Like
Shannon
Shannon
May 24
Replying to

Thanks for the comment! I'm glad it helped! Good luck and keep cranking!

Like

© 2020 Shannon B. Eldridge-Kuehn

  • LinkedIn
  • Twitter
bottom of page