Default to safe force pushing in Git (without aliases)
Tags: showdev, git
Published: 2020-02-27 14:45:43

---
title: Default to safe force pushing in Git (without aliases)
published: true
description: Check out this neat little shell function to help you force push safely.
tags: showdev, git
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/zskj6bsxul1j4fb7t998.png
---

A few days ago I posted some [Git tips and tricks](https://dev.to/jody/another-list-of-tips-and-tricks-to-improve-your-git-workflow-459j), one of which was that you should use `--force-with-lease` any time you want to use `--force`.

Why should you do this? Basically `--force` can be destructive and `--force-with-lease` is a little more careful before changing history. Let's hear from [this Atlassian blog post](https://blog.developer.atlassian.com/force-with-lease/) again:

> What `--force-with-lease` does is refuse to update a branch unless it is the state that we expect; i.e. nobody has updated the branch upstream. In practice this works by checking that the upstream ref is what we expect, because refs are hashes, and implicitly encode the chain of parents into their value.

If you're already familiar with this concept you might be using an alias to invoke `--force-with-lease`. Mine looks like this:

```zsh
lease = push --force-with-lease
```

This allows me to type `git lease` and have the same effect as `git push --force-with-lease`. If this works for you then perfect! You don't really need to read any further.

The problem I have is that in a lot of my command line usage, Git and otherwise, I regularly type `--force` for various reasons. It's muscle memory that I've developed, and I regularly find myself force pushing the wrong way. It's bad and I feel bad. So bad that I spent some time recently working on this quick and dirty (but also kind of neat) solution to short circuit my use of the bad force altogether:

{% gist https://gist.github.com/jodyheavener/ad97cccaf2010ffc3935beea98c9f717 file=git-push.bash %}

<sub>(Writing shell commands is not my strong suit, so if you see ways this can be improved I am all ears.)</sub>

This is a shell function I've added to my ZSH profile. Here's a quick breakdown of what it does:

- First, it overrides the `git` command. (I know it's probably not a great idea overriding git, don't email me, do this at your own risk, whatever)
- It looks for use of the `push`. If that isn't found, continue on regularly.
- If you're using `push` and _not_ `--force`, continue on regularly.
- If you _are_ using `--force`, replace that argument with `--force-with-lease`.
- If you're using `--force` and you really need it, you can add `--seriously` to avoid having it replaced with `--force-with-lease`.
- In any case, any other arguments are still applied regularly.

So now we can do the following:

```
# Regular use of --force-with-lease unaffected
➜  example git:(master) ✗ git push --force-with-lease
Everything up-to-date

# Use of --force overridden 
➜  example git:(master) ✗ git push --force
Detected use of --force! Using --force-with-lease instead. If you're absolutely sure you can override with --force --seriously.
Everything up-to-date

# Use of --force not overridden if --seriously
➜  example git:(master) ✗ git push --force --seriously
Heads up! Using --force and not --force-with-lease.
Everything up-to-date
```

That's it! Now I can lazily avoid having to change my ways. Would love to hear what you think.