Hacker News new | ask | show | jobs
by acallaghan 15 days ago
I'm also like this, rebasing feature branches onto main - I however have one suggestion when it comes to the push back up to origin

Instead of

`git push --force`

always use

`git push --force-with-lease`

https://git-scm.com/docs/git-push

This probably should be the default in git (as in there should be a `git push --force-without-lease` instead) and asks git to make sure the commits locally on your branch are up-to-date with those on remote/origin. It then fails if you try to overwrite commits that you haven't seen, and has saved me a few times when working between computers on the same project when i could have lost history on the remote that i failed to fetch.

1 comments

--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.

>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?
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