As a developer, you‘ll inevitably encounter situations where you need to force push changes to a Git repository. Maybe you rebased a branch and need to overwrite the remote history. Perhaps you accidentally pushed sensitive data and need to remove it from the commit history.

While git push –force is a useful tool, it can also cause headaches if not used properly. Force pushing changes the remote history, which can disrupt other developers working on the same branch.

In this comprehensive guide, we‘ll cover:

  • What force pushing is and when you may need it
  • The dangers of force pushing and how to avoid problems
  • Step-by-step instructions for properly forcing a push
  • Best practices for using git push –force

By the end, you‘ll understand how to safely and responsibly force push changes to a shared Git repository.

What Is Force Pushing in Git?

Normally when you git push changes to a remote branch, Git prevents you from overwriting commits that aren‘t in your local repository. This safeguard helps prevent you from accidentally removing other developers‘ work.

Force pushing circumvents this protection by allowing your local branch to override the remote history, even if your local branch doesn‘t contain the same commits.

Here is a quick example to demonstrate normal pushing versus force pushing:

# Normal push - gets rejected because remote contains commits not in local
(master) $ git push origin master 
To https://github.com/foo/bar.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to ‘https://github.com/foo/bar.git‘
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: ‘git pull ...‘) before pushing again.
hint: See the ‘Note about fast-forwards‘ in ‘git push --help‘ for details.

# Force push - overwrites remote history even though commits differ
(master) $ git push --force origin master 
Enumerating objects: 15, done.
Counting objects: 100% (15/15), done.
Delta compression using up to 8 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (15/15), 1.68 KiB | 560.00 KiB/s, done.
Total 15 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
To https://github.com/foo/bar.git
 + 94b7c5c...19210fa master -> master (forced update)

As you can see, force pushing overwrites the remote branch even though the local and remote histories differ.

When Should You Force Push?

There are a few situations where force pushing is necessary to get the remote Git history into the state you want:

1. After Rebasing a Shared Branch

Rebasing rewrites commit history. So if you rebase a branch that you‘ve already pushed to a shared repository, your local history will diverge from the remote. Pushing normally will be rejected. Force pushing is required to overwrite the remote commits with your rebased ones.

2. Reverting a Commit That‘s Already Been Made Public

If you accidentally commit sensitive data like passwords or keys, force pushing can help rewrite history to remove the problematic commits. Just revert the commits locally, then force push to undo them on the remote.

3. Resolving Merge Conflicts from an Old Branch State

Let‘s say a collaborator merged a pull request 3 commits back on a shared branch. You later check out and merge from the old branch state, causing confusing merge conflicts.

Force pushing would overwrite those bad merges, resolving the issues by making the branch match your now-fixed local state.

4. Changing an Open Pull Request‘s Branch Point

Sometimes when requesting feedback on a pull request, you need to incorporate suggestions that involve changing commits before the pull request branch point.

Force pushing lets you seamlessly update a pull request branch after altering history through rebasing or reverting.

Dangers of Force Pushing

While force pushing serves legitimate purposes, you need to exercise great care. Force pushing changes the remote history, which can wreak havoc for your teammates in some situations.

Some potential pitfalls include:

Overwriting Other Developers‘ Work

If another developer has pushed commits since you last pulled, force pushing can undo their work. For example, Dev 1 clones the repo and makes some changes. Dev 2 does the same, force pushes, then Dev 1 tries to share their work but ends up having to re-do commits.

Conflicting Branch Histories

Force pushes can leave remote branches in broken states if you aren‘t careful with history rewrites. For example, let‘s say the master branch contains critical commits that other teams rely on. If you force push master and revert or remove those commits, pushes and fetches against other branches may fail.

Confusing Git Tools and Services

Many Git services like pull requests assume a linear commit history. Force pushing can create headaches. For example, if someone reviews your pull request then you force push, their comments may end up misaligned on altered or removed commits.

Unauthorized Changes to Public History

On collaborative projects, you generally shouldn‘t force push shared branches without coordinating with the rest of the team. Forcing changes unexpectedly can undermine others‘ work and be disruptive.

Step-By-Step Guide to Force Pushing

Now that you understand the basics of force pushing and some of the hazards involved, let‘s walk through the proper process for forcing push changes.

Follow these seven steps, and you can avoid issues when overwriting remote history.

1. Discuss With Your Team

Before force pushing, discuss it with your collaborators when possible – especially for shared repositories with active development.

An quick Slack message or email explaining what you‘ll change and why helps set proper expectations.

For smaller fixes, a git commit message noting your force push may suffice. But for substantial history rewrites, confirm no one has important unmerged work to avoid conflicts.

2. Pull Before You Push

One of the cardinal rules of Git is to pull before you push. Forcing changes without pulling is asking for merge trouble.

Always fetch remote commits and rebase on top of the latest branch state before force pushing:

(my-branch*) $ git fetch
(my-branch*) $ git rebase origin/my-branch
(my-branch*) $ git push --force

This updates your local history, avoiding conflicts and surprises.

3. Limit Scope

When force pushing, overwrite the minimum commits possible to accomplish your goal.

For example, if you just need to amend a commit message, rebase interactively and only force push the amended commit by hash. There‘s rarely a case where force pushing hundreds of commits is wise or safe.

4. Force Push from Updated Local Branches

In general, avoid force pushing branches other than the one you fetched and rebased onto latest.

Force push from topic branches based on the now-updated history. Otherwise, mismatches between branch histories can occur.

5. Test Behaviorally Before and After

Force pushing can seem to work while causing subtle issues. Thoroughly test application behavior before and after to spot potential flaws introduced through rewriting history.

For web apps, check pages and API endpoints. For CLI tools, run major invocation flows. Catch issues early.

6. Warn Teams and Deploy Gradual Rollouts

When force pushing shared infrastructure repositories, warn users about potential impacts to workflows. Consider gradually rolling out related applications to catch failures the force push may introduce.

7. Retain Separate Backups of Old References

In an ultra-cautious approach, you can retain backups of branches before forcing changes. For example:

(master) $ git branch old-master 
(master) $ git push origin old-master
(master) $ git push --force origin master

This lets you easily restore to the previous state if problems arise.

Git Force Push Best Practices

Beyond the proper process, adhering to best practices helps avoid issues when force pushing:

Make Judicious, Surgical Changes

As covered earlier, limit force pushes in scope. Avoid excessive, unnecessary history rewrites.

Force Push from Throwaway Branches

When experimenting, create throwaway branches. Force push brazenly without worrying about disrupting other developers.

Communicate Changes Clearly

Use clear, descriptive commit messages noting forced updates. Call attention to significant alterations developers should be aware of.

Review PRs Before Merging

Scrutinize pull requests containing force pushes thoroughly before allowing them into mainline branches. Make sure quality and behavior checks out.

Agree to Guidelines as a Team

Establish team policies dictating appropriate use cases and procedures for force pushing changes. Removing ambiguity helps avoid problems.

Audit Shared Repository History

Occasionally review shared branch logs to check for unexpected revisions. Many build tools integrate with Git, allowing history audits through CI/CD pipeline logs. If you spot suspicious or confusing activity, address it with your team.

Alternative Approaches to Force Pushing

Sometimes techniques like:

  • Reverting problematic commits
  • Creating fixup commits
  • Cherry picking changed commits

…Can solve issues without force pushing and rewriting history.

Explore these alternatives first, when practical. Ultimately though, force pushing is a useful tool when applied judiciously.

Conclusion

While git push –force provides a convenient, quick way to overwrite repository history, reckless force pushing causes more problems than it solves. But when applied carefully according to the best practices outlined here, it enables fixing mistakes and updating shared branches without losing work or corrupting Git timelines.

Now that you understand the pitfalls of uncontrolled force pushing along with a safer process, you can confidently use this powerful command without anxiety or unintended disruption.

Force pushes no more fear – just responsible, surgical changes. Full steam ahead on your Git projects!

Similar Posts