workflow
Improve your GitHub workflow with better repository defaults
Starting a new project? Set your team up for success with these opinionated GitHub repository settings.
Creating a GitHub repository is one of those “set it and forget it” moments at the start of a project that maybe doesn’t get so much attention. But there are some interesting things buried in the repository settings pages that can improve your team’s PR review process, add clarity to your documentation practices, and speed up how you deliver features.
Here’s my checklist for setting up a new GitHub repo:
- Enforce the squash-and-merge strategy for PRs
- Turn on branch automation tools
- Disable redundant project management features
For fun, I also created a script to apply these settings using the GitHub CLI, which I’ll share at the end of this post. 🤓
Enforce the squash-and-merge strategy for PRs
Delivering code as a team requires some level of code review and a shared understanding of when and how each developer’s contributions are merged and integrated. For new projects I always use GitHub Flow as a starting point.
In GitHub Flow, developers branch from
main
and deliver code via peer-reviewed pull requests with CI checks.
But how do you merge those PRs? By default, GitHub gives developers a drop-down of three choices: merge, squash, or rebase. I recommend the squash strategy. It makes the history of the main branch easy to understand, and frees developers from tedious tasks like manual rebases.1
To enforce this, go to the repository Settings and scroll down to Pull Requests. Leave squash turned on and turn off the merge and rebase strategies:
To further enforce the squash philosophy, you can navigate to Branches and enable the following branch protection option for your main branch:
Turn on branch automation tools
Even with squashing, branch-based workflows like GitHub Flow end up creating some busywork. For example, over time PR branches accumulate and clutter up the GitHub UI. It is good “repository hygiene” to delete feature branches once the associated PR is merged, but this manual step is easy to forget.
In the repository Settings, turn this feature on to have GitHub do the busywork for you:
Another point of friction in PR workflows is keeping your feature branch up to date. While you are working on a feature branch, the main branch can become a moving target. A teammate’s refactor on main
might break your code when it comes time to merge your PR. Or maybe someone added a utility on main
that you need for your feature.
Ultimately, the best way to minimize this friction is to maintain good communication with your teammates and strive for small PRs with short-lived feature branches. But even then, you may still encounter this challenge on occasions when the main branch evolving rapidly.
GitHub has a one-click solution for this that you can also enable on the Settings page:
main
.With this feature enabled, you can now bring your branch up to date with the main branch with a single click. No more rebasing hassles. (Yes, this button introduces merge bubbles into your feature branch, but that’s OK! The PR squash strategy gets rid of them.)
Disable redundant project management features
Finally: GitHub enables a bunch of project management features by default that are geared towards open source projects. Most private projects don’t need these. In fact, your team probably has an agreed-upon solution already in place: something like Pivotal Tracker, Linear, Jira, Trello, etc.
Leaving GitHub’s project management features on can confuse collaborators about how to report bugs or where to find documentation. Go to the repository Settings page and turn all of these features off:
- Wikis
- Issues
- Sponsorships
- Discussions
- Projects
Apply these recommendations using the GitHub CLI
There are at least 30 checkboxes in the GitHub repository settings UI, if you include branch protection rules. Wouldn’t it be fun to automate setting them up? Turns out the GitHub CLI allows you to do just that!
$ gh repo edit \
OWNER/REPO \ # replace with the name of your repository
--enable-wiki=false \
--enable-issues=false \
--enable-discussions=false \
--enable-projects=false \
--enable-merge-commit=false \
--enable-squash-merge=true \
--enable-rebase-merge=false \
--delete-branch-on-merge=true \
--allow-update-branch=true
repo edit
command provides an easy way to set some repository options. This script applies the recommendations of this article to an existing repo.
$ gh api \
-X PUT \
/repos/OWNER/REPO/branches/main/protection \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
-F 'required_status_checks=null' \
-F 'enforce_admins=null' \
-F 'required_pull_request_reviews[required_approving_review_count]=1' \
-F 'restrictions=null' \
-F 'required_linear_history=true'
api
command. This script turns on Require linear history and requires 1 approving review to merge PRs against the main
branch.
Further reading
- GitHub Flow (GitHub quickstart)
- Managing your repository’s settings and features (GitHub docs)
- About merge methods on GitHub (GitHub docs)
- How to install
gh
(GitHub CLI README) - gh repo edit (GitHub CLI man page)
- Update branch protection (GitHub REST API docs)
- Update Branch Protections API Documentation missing for GitHub CLI (GitHub CLI feature request)
If you’ve run into edge cases with squashed PRs in the past, it is worth mentioning that git has gotten much better at handling complex squash-and-merge workflows as of v2.38 (released October 2022).
-
The squash-vs-merge debate is a deep topic. I plan on elaborating on it in a future blog post. ↩