Once a code base is sophisticated enough to require both a public, customer-facing production environment and private development environment, it becomes vital to prevent potentially breaking development changes from being accidentally pushed to production.
This post will go over three methods of preventing development changes from being pushed to production:
- Changing the Remote’s URL
- Using Git Hooks
- Adding Branch Protection

Changing the Remote’s URL to Prevent Accidental Pushes to the Production Branch
This method prevents accidentally pushing in-development changes to the wrong environment by changing the remote’s URL using git CLI commands:
# git command to change remote's URL
$ git remote set-url --push <REMOTE_NAME> <NEW_URL>
By adding the –push flag to the command, only the push URL is manipulated. So it is still possible to pull from that remote. Then, we want to set the push URL to anything that won’t be a real endpoint such as no_push. Now, when someone accidentally pushes their changes, the URL is invalid and the command will fail.
# git command to disable the push
$ git remote set-url --push <REMOTE_NAME> no_push
# Example
$ git remote set-url --push prod no_push
# git command to list the remote repositories
$ git remote -v
origin <https://github.com/user/repo_forked.git> (fetch)
origin <https://github.com/user/repo_forked.git> (push)
prod <https://github.com/user/repo.git> (fetch)
prod no_push (push)
# When one accidentally push changes to prod with push URL set to no_push
$ git push prod
fatal: 'no_push' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
If you need to push code to that remote in the future, you can simply re-enable the push by doing the following.
$ git remote set-url --push <REMOTE_NAME> <REPO_URL>
# Example
$ git remote set-url --push prod <https://github.com/user/repo.git>
# git command to list the remotes
$ git remote -v
origin <https://github.com/user/repo_forked.git> (fetch)
origin <https://github.com/user/repo_forked.git> (push)
prod <https://github.com/user/repo.git> (fetch)
prod <https://github.com/user/repo.git> (push)
Using Git Hooks to Prevent Accidentally Pushing Development Changes to a Production Branch
Another effective method to prevent pushing development changes to a production branch is to use Git Hooks . Git Hooks are scripts that run automatically at certain points in the Git lifecycle, such as before a commit is made, before pushing changes, or before merging. By leveraging Git Hooks, you can enforce additional checks before changes are pushed to a production branch.
Setting Up a Pre-Push Hook
The pre-push hook is a powerful tool for intercepting a push operation before the changes are sent to the remote repository. You can use this hook to check whether the branch being pushed is the production branch (e.g., main or production), block the operation, and display an error message.
1. Navigate to Your Local Git Hooks Folder
In your local repository, Git Hooks are located in the .git/hooks directory. If you’re working in a shared team environment, make sure to create a shared version of the hooks to ensure uniformity across all developers’ machines. For now, let’s focus on setting up the pre-push hook.
2. Create or Modify the pre-push Hook
If the pre-push hook does not already exist, you can create a new file called pre-push in the .git/hooks/ directory. If it does exist, you can modify it.
Example of a pre-push hook script:
#!/bin/bash
# Get the current branch name
current_branch=$(git rev-parse --abbrev-ref HEAD)
# Define your production branches (you can add more as needed)
protected_branches=("main" "production")
# Check if the current branch is a protected branch
if [[ " ${protected_branches[@]} " =~ " ${current_branch} " ]]; then
echo "Error: You are trying to push to a protected branch ($current_branch)."
echo "Please ensure you are pushing to a non-production branch."
exit 1
fi
# Allow the push to continue if not pushing to a protected branch
exit 0
3. Make the Hook Executable
After creating or editing the hook, make it executable by running the following command:
chmod +x .git/hooks/pre-push
4. Push Attempt to a Protected Branch
Now, when a developer tries to push changes to a protected branch (e.g., main or production), the pre-push hook will run and display an error message, preventing the push. For example:
$ git push origin prod
Error: You are trying to push to a protected branch (prod).
Please ensure you are pushing to a non-production branch.
5. Allowing Pushing to Other Branches
If the developer tries to push to any other branch, the push will be allowed without interference, as the hook only prevents pushes to protected branches.
By using the pre-push hook, you automate a safety check that ensures no one accidentally pushes code to the production branch. This is especially useful when working with local or remote repositories that don’t have branch protection rules in place. Even if a developer forgets to follow the standard process or is working in a rush, the hook acts as a last line of defense to catch potentially catastrophic errors before they reach your production environment.
Adding Branch Protection to Prevent Accidental Pushes to the Production Branch
Branch protection helps ensure that critical branches, such as main or production, are not accidentally modified. By enforcing rules that restrict who can push or merge to production branches, you significantly reduce the risk of errors and issues making their way into a production environment.
Steps to Set Up Branch Protection on GitHub:
1. Navigate to Your Repository Settings
Go to your repository on GitHub, then click on the Settings tab. This is where you can manage many aspects of your repository, including branch protection.
2. Access Branch Protection Settings
On the left sidebar, select Branches. Under the “Branch protection rules” section, click on the Add rule button.
3. Choose the Branch to Protect
In the “Branch name pattern” field, type the name of the branch you want to protect (e.g., main, production, or any other branch that holds your production code).
4. Enable Protection Rules
Once you’ve selected your branch, enable the rules you want to enforce. Here are some key options:
- Require pull request reviews before merging This ensures that all changes to the protected branch must go through a code review.
- Require status checks to pass before merging This ensures that all automated tests (CI/CD) pass before the code can be merged.
- Include administrators This enforces the same protection rules on repository administrators, preventing accidental changes even by people with elevated permissions.
5. Save the Rule
After configuring the protection settings, click Create or Save changes to activate the protection rule.
Once branch protection is enabled it is impossible for developers to push changes directly to production branches. Instead, they must use pull requests, which can be reviewed and approved before merging. This adds an additional layer of safety, especially in larger teams where collaboration and testing changes are key to overall project success.
Do Embedded Firmware Right with Dojo Five on Your Team
In conclusion, by using remote URL settings in combination with other safeguards such as Git Hooks and branch protection, it is possible to prevent accidentally pushing changes to critical branches. Spending a few minutes on prevention will certainly save you from some hassle in the future.
Are you looking to modernize your embedded firmware development and support processes? You can book a call with us to get the conversation started. Or if you’re into DevOps, you can sign up for our EmbedOps platform. We look forward to hearing from you!


