How to Avoid Pushing In-development Changes to The Production Repository

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
Book a Call with Dojo Five Embedded Experts

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 pushes 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:

  1. Require pull request reviews before merging
    This ensures that all changes to the protected branch must go through a code review.
  2. Require status checks to pass before merging
    This ensures that all automated tests (CI/CD) pass before the code can be merged.
  3. 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!

Discover why Dojo Five EmbedOps is the embedded enterprise choice for build tool and test management.

Sign up to receive a free account to the EmbedOps platform and start building with confidence..

  • Connect a repo
  • Use Dev Containers with your Continuous Integration (CI) provider
  • Analyze memory usage
  • Integrate and visualize static analysis results
  • Perform Hardware-in-the-Loop (HIL) tests
  • Install the Command Line Interface for a developer-friendly experience

Subscribe to our Monthly Newsletter

Subscribe to our monthly newsletter for development insights delivered straight to your inbox.

Interested in learning more?

Best-in-class embedded firmware content, resources and best practices

A phone projecting app icons above

Medical Device Documentation

If you’ve ever built a medical device, you’ll know how much documentation is required. The amount of documentation required by regulatory bodies like the FDA can intimidate even the most stalwart engineer. But they require it for good reasons. In fact, when you have a smart plan for documentation, you may find that it becomes helpful instead of intimidating. With the right approach, maintaining the necessary documentation means that you are also maintaining a good development process. Here, we’ll break

Read More »
Puzzle pieces on a light grey background

The Git Cherry-pick and Git Rebase Interactive Combo

Version control is necessary, but using it well is an art. Today I am going to give an overview of two Git commands that I found helpful during software development, git cherry-pick and git rebase in interactive mode. Git Cherry-pick Software development is often a team game. To work within the planned schedule, each developer will implement features in their own feature branches. But sometimes there are changes that everyone wants! git cherry-pick is a Git command that lets the

Read More »
Automating Reliability Engineering with CVE Scanning & EmbedOps (Part 3)

Automating Reliability Engineering with CVE Scanning & EmbedOps, Part 3

Parts 1 and 2 of this series showed just how easy it is to automate unit testing and hardware-in-the-loop (HIL) testing with Dojo Five EmbedOps, a build integration and automation platform for commercial embedded and IoT device development teams. Both articles provided practical guides for using EmbedOps to quickly build the typical tests that a developer might conduct for a Bluetooth Low Energy (BLE)-enabled sensor, such as finding overflow bugs or verifying over-the-air (OTA) device firmware updates (DFUs). The aim

Read More »