Master Git
Protect git branch and prevent master push
Background #
I've only really ever developed application by myself but I work in a way that I hope to be able to work in a team. I still have plenty to learn but the basic idea is that I have 2 main branches master
and develop
. I setup develop
as my default branch and the master
branch is what is deployed as Production by merging changes from develop. So this is just a note to myself how to create this setup and it might be of some use to anyone else trying to organise their process a bit without making things to complicated.
The git rebase master to branch operation is a dangerous one. Typically you should only clean up Git branches local to your workstation, not branches pulled from a central repository, as master typically is. Instead of a git master rebase, you might want to look at the git rebase branch to master operation instead. This allows you to squash Git commits and manipulate the history of branches. The above command will just fetch all the remote branches to your local. Update the upstream remote HEAD git remote set-head origin -a. The above command will query the remote host for the HEAD upstream and it updates that upstream in the local. Rename the default branch git branch -m master default. This is the same as the old one. Git has 7 repositories available. Follow their code on GitHub.
Branch protection #
$ git pull origin master. This command downloads the remote repository branch “master” into our local repo. Next, I created three text files in the local repository. This is followed by running the git add command under the master branch: $ git add tst1.txt $ git add tst2.txt $ git add tst2.txt. Maybe MongoDB has this problem, but not git. So there's no 'master/slave' metaphor in Git to speak of. Words change meanings over time 'Master' is a term used the recording industry, or to talk about skill ('Master of Science', 'Kung Fu Master' etc.). I'm not a native English speaker so 'master' was strange to me too, but in American English.
My first step is creating the develop branch from master and pushing this up to Github. You could also do this by simply creating a branch from the GUI.
Once the develop
branch is in the repo you want to navigate to Settings > Branches
and set the develop branch you just created as default.
Branch protection rules #
This is of course optional and you could leave the master
as default. I just prefer doing it this way to further protect the master
branch. The next step is protecting the develop
branch from deletion by simply creating a Branch protection rule by clicking on the add button. In Branch name pattern add the text develop
without selecting anything else. This will now protect the branch from being deleted.
master
branch will also need to be protected in the same way. You should be left with two rules that have nothing currently checked but this will protect both of these.
Disable master push #
In the .git/hooks
folder you need to create a file pre-push, no file extension and add the following to the file:
The script checks the current branch being pushed and compares it to the protected branch, in this case master. A simple if statement and stop pushing directly to the master branch and you will need to create a pull request to merge changes. You could do the same for the develop branch to also protect that. This is a simple solution for me to at least protect those branches I want to and forces me to create PR's everytime I want to make a change.
Workflow #
Master Gita Master Life
Having the master
and develop
branches I will pull my develop branch and then create another branch for the work I want to work on, for example:
The new feature is not in the repository and I can create a pull request into develop to check the changes live before finally merging them into production.
The Internet Engineering Task Force (IETF) points out that 'Master-slave is an oppressive metaphor that will and should never become fully detached from history' as well as 'In addition to being inappropriate and arcane, the master-slave metaphor is both technically and historically inaccurate.' There's lots of more accurate options depending on context and it costs me nothing to change my vocabulary, especially if it is one less little speed bump to getting a new person excited about tech.
You might say, 'I'm all for not using master
in master-slave technical relationships, but this is clearly an instance of master-copy, not master-slave.'
UPDATE: There is Good analysis of the whole main branch convo in the Git Rev News: Edition 65. Git likely uses master in the context of 'master copy' or 'master recording.'
So we see that while the word master doesn't always connote slave, for many, it's evocative via basic word-association and they just don't want to look at the word on their prompt all day. Choice is cool.
I have had dozens of git repositories that have 'master' as the main branch. Changing that would be a hassle right?
Let's see. I'll just 'git branch -m master main' and then push it back! Remember that -m is --move so your history isn't changed! Even better I can 'git push -u origin main
' to set the upstream at the same time.
That was easy.
NOTE: Changing the default branch to 'main' also has the benefit of starting with 'ma' so that autocomplete <TAB> muscle memory still works. Another great option for your main github branch is 'latest.' The goal is to just be unambiguous.
Now I just need to change my default branch in my GitHub settings for my repository.
I can also update the tracking branch manually as seen here, but if you use git push -u origin main
it'll do both.
The last thing to think about is if you have a CI/CD, GitHub Action, Azure DevOps pipeline or some other build system that pulls a specific branch. You'll just change that to main. However, usually unless your CI explicitly calls for a branch by name, changing master to main will 'just work!'
NOTE: For more complex repos also check your protected branch rules.
This is because -m is --move and all your reflog is unchanged!
TL;DR in conclusion:
Updating local clones
If someone has a local clone, then can update their locals like this:
From the tweet above (Thanks Brad from XUnit.net!), these steps
- Go to the master branch
- Rename master to main locally
- Get the latest commits from the server
- Remove the link to origin/master
- Add a link to origin/main
- Update the default branch to be origin/main
Master Gitignore
You can add an alias 'git new
' that will default to whatever starting branch you like. (NOTE: This is no longer needed, set below)
UPDATE!As of Git 2.28 you don't need an alias as above, as there is a new config option called init.DefaultBranch. Just set it and forget it.
Hope this helps! Other good names are latest, trunk, and stable!
Sponsor: Have you tried developing in Rider yet? This fast and feature-rich cross-platform IDE improves your code for .NET, ASP.NET, .NET Core, Xamarin, and Unity applications on Windows, Mac, and Linux.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.