In my book Git for Humans, published in 2016, I made copious references to master
as the primary branch name used in Git repositories.
The term master
can refer to a "master copy," meaning the original or canonical version of something from which other copies are made. But its primary meaning in the English language is "a person who has general authority over others." And, especially in American and British English, it's hard to separate the word "master," and that meaning of it, from another related word: "slave."
If we're being honest, folks in tech have known that "master" and "slave" are problematic terms for a while, even if they haven't felt motivated to change them. There are those who say that if these words refer to objects or systems, rather than people, then they can't be offensive, just as people argue that tech is a meritocracy and algorithms can't be biased. These arguments are wrong. You can't separate the word "master" from its real-world connotation — in fact, it's the connotation that gives it meaning. (How is a "master copy" considered authoritative and canonical if "masters" don't rule over other human beings?)
Anyway, I fully support efforts being made now (however belatedly) to remove the word "master" from our tech lexicon, including from our Git repos. GitHub has even announced they are working on changing the default for everyone, though they haven't shipped this yet, and it will probably only apply to newly created repositories.
It may not be feasible to update the Git for Humans manuscript to remove all references to master
(but I'll be reaching out to the awesome team at A Book Apart to find out what can be done), but in the meantime here is some information on how to rename your primary branch and set different defaults in your favorite Git-based tools.
While master
is a long-standing convention, one of the great things about Git is that it doesn't really require your main branch to be named master
(or anything else). You can choose any name you want, and you can change names at any time, so long as you're willing to do some work.
I chose to rename my personal site's main branch to stable
, as a subtle reminder that stuff in that branch is meant to be, well, stable (whereas breaking changes can and should live in other branches). But main
works too, as would primary
, production
, fhqwhgads
, or anything else you like.
In an existing Git repo, the simplest way to switch names away from master
is to just create a new branch and start using that one instead:
git checkout master # if you're not already there
git checkout -b stable
Alternatively, if checking out master
is not convenient, you can use git branch
to create a new branch based on its current commit:
git branch stable master
Either way, your master
branch will be left intact, and a new stable
branch is created that's an identical copy of master
, which you can use instead for all the things you used to do with master
.
Before you forget, make sure to push stable
to GitHub (or whatever remote server you use):
git push -u origin stable
At this point, a new stable
branch exists, but no one is using it yet. Next we need to work on the hard part: switching all the people and things over to the new branch.
Naming the primary branch master
is a convention, not a rule. But because it's a strong, long-lived convention, a lot of your Git tools probably assume that you're following it. Fortunately this can also be easy to change.
Open your repo page on GitHub while signed in, and click on the Settings tab.
In the Settings page, click Branches in the left-hand navigation. Then, on the right-hand side, you'll see a drop-down that lets you change the name of your default branch. (Remember, though here you see me changing it to stable
, but you could set it to main
or whatever name you chose.)
Once this is done, new pull requests will automatically be set up to merge into stable
, and git clone
s from GitHub will also check out stable
by default.
A whole lot of people use Netlify to publish and host static web sites, and a lot of those people use Netlify's Git/GitHub integration to automatically publish changes when you push to your default branch.
If you (like me) are one of those folks, you'll need to go into your Netlify site settings to select a new production branch. This is under Build & deploy > Deploy contexts.
If you have complex integrations with your Git projects, such as continuous integration or deployment systems, before making these changes — and certainly before you delete or disable the old master
branch — you should talk with your team and make a plan for how to update everything to use a new name.
Depending on the size and scale of your project, this may require changing some files in your repo or some settings in your hosting or other service providers, but may also require some dev-ops type work to plan and roll out a change. In my opinion this work is worth doing, and the sooner the better, but you should balance the urgency of adopting more inclusive terminology with ensuring a stable experience for your users.
Sadly, Git doesn't have any such thing as "branch redirects." If all you do is create a new branch named stable
, your teammates may keep pushing changes into master
, and systems that hook into your repo will keep treating master
as the main branch.
Hopefully getting collaborators to change names should be as simple as talking to them, telling them you think stable
(or whatever) should be the main branch name going forward, and that they should treat it as such.
Of course, muscle memory can be very strong, and even on a team that agrees to use stable
instead of master
, someone might push changes to master
out of habit. If you want to make pushes to master
trigger an error, one simple thing you can do is to replace the content on your master
branch with a commit that's disconnected from the rest of your repo.
First, you'll want to create an "orphan" branch, which (as the name implies) is a branch/commit with no parent.
git checkout --orphan no-masters
Then remove all the content from the repo while in this branch. Using git rm
(as opposed to regular 'ol rm
) will only delete files and folders that are checked into Git, leaving behind ignored content.
git rm -fr .
Depending on the technology stack you use, this may leave behind some content that had previously been hidden by .gitignore
, which will now show up when you run git status
. You can restore the gitignore
file to make sure these files are not committed or deleted:
git checkout stable .gitignore
Lastly, you may want to leave a note explaining why this branch is empty. We'll add and commit a README.md
Markdown file with the following text:
# This branch is deprecated
This project's primary branch is now called `stable`.
You should `git checkout stable` and `git pull origin stable` from now on.
Then you can commit these changes:
git add .gitignore README.md
# … output deleted …
git commit -m "Deprecation message for `master` branch"
Because this is an orphaned branch, if you run git log
you'll only see this commit, none of the history before it:
git log --oneline
> cd2b2c2 (HEAD -> no-masters) Deprecation message for `master` branch
OK, now for the scary part — replacing master
with this content. Which means deleting your old master
branch:
git branch -D master
This will delete master
locally, allowing you to create a new master
branch that points to this new, empty-except-for-deprecation-message commit.
git branch master no-masters
If you were to then git checkout master
, you'll see the deprecation message.
git checkout master
git log --oneline
> cd2b2c2 (HEAD -> master) Deprecation message for `master` branch
Whew. Okay. One last step: pushing this master
branch to GitHub. Because this is a new, orphaned branch, you will need to force-push. This may (hell, probably will) break any integrations you have hooked up to master
, so you may want to wait until your team and infrastructure are fully migrated over to main
until you do this.
git push -f origin master
Ahhhhhhhhh, so nice to have that done. Here's the deprecation message as shown on one of my GitHub repos:
Because master
now points to this orphaned commit, whenever you or someone on your team tries to pull from it Git will raise an error:
git pull origin master
From <your-repo-url-here>
* branch master -> FETCH_HEAD
fatal: refusing to merge unrelated histories
If only it was this easy to break free from history in real life.