Hacker News new | ask | show | jobs
by kazinator 18 days ago
--force-with-lease serves no purpose.

If you are sure that the repo you are pushing to is a stable target (nobody else is accessing it), you just use --force.

If the repo you are pushing to is a moving target, you ... don't force push to it. Or else you warn all the repo users that you are about to rewrite history. Which means they not only should refrain from pushing, but have to be prepared for a second announcement which informs them that the rewrite is done; they must then fetch the rewritten head and fix up their unpublished work against the non-fast-forward change.

Now it may be that --force-with-lease allows you to sneak in non-fast-forward changes without losing newly introduced upstream changes: but that assumes it's a good idea to be doing that sort of thing without communicating with your team. I.e. as long as we can sneak in a non-fast-forward change without accidentally/unknowingly deleting anyone's work, we are peachy; no need to coordinate.

3 comments

>If you are sure

--force-with-lease exists for the scenario where you are sure, but wrong.

I don't see how you could be wrong in knowing whether you're the only user with push access to the remote repo, or there are others.
You could have multiple computers, checkouts, or worktrees pointing at the same branch
You'd have to interrupt your own activity of synchronizing one of your downstream repos with your upstream, and force-publishing something back upstream, by switching to another one of the downstreams and publishing something into the upstream, which is then clobbered when you resume the original activity. Basically, split personality disorder where some of the personalities are not aware of the others.

All of this still overlooks the fact that the changes are not lost. Say someone (like one of the personalities in your head you don't know about) publishes a change which you unknowingly clobber with a "git push --force". That someone will notice when they fetch the repo: it has diverged from their clone and when they look at the history of master vs origin/master, they will see that their commit which they are sure they pushed does not appear in origin/master.

If you have multiple downstream checkouts and manage to clobber something with force pushes, you can recover. Then have a word with yourself and work smarter going forward.

All force-with-lease does it stop you from clobbering rather than you having to realise somehow that you did that. It seems like a no-brainer. What's the problem with it?
The only situations in which I would use a git push --force would be in which I have carefully considered what state the remote is in, and what state I want it to be be in, and I know that it's not a moving target it any way in between checking its state and doing the force.

Already, "git push" stops from clobbering: it warns that your proposed push is non-fast-forward and that you need --force.

If you are using git as intended, that's all the warning you need.

I understand that there are dubious workflows out there where a repo has multiple downstream users and they are all doing "git push --force", without coordinating with each other. They need a double force to make sure that they are clobbering what they think they are clobbering.

If that's not you (which it arguably shouldn't be, and certainly isn't me), you don't need to know about force-with-lease.

The only thing I would ever do with --force-with-lease is go "oh", and immediately repeat the command with --force, knowing that I'm in a situation in which the check is not applicable.

Even if the force were erasing a new commit that came from another repo, I would know that. Like I pushed something into upstream U from repo B, but I'm fixing the situation out of repo A which hasn't picked up the change. Yes, I know what I'm doing, that's why I'm using --force, and don't require --simon-says-force. I want the chain of commits I now have in A to be exactly what is in U, as a rare exception to normal git use. After I'm done from A, I will switch back to B, do a "git fetch" and probably "git reset --hard origin/master" to make B look like U.

I wouldn’t say it serves no purpose. It is useful when rewrites are tolerable and loss of history is not. It’s the default when using tools like jj, because the expected workflow wraps git in a way that force pushes are frequent and expected, but blowing away someone else’s work by mistake is not.
My point is really that the default --force is dangerous for new/sleep deprived users, or ones that kinda understand but don't - where as --force-with-lease is not and is always safe. --force-with-lease should just be default