4

Is there a way to use git push -f, but only origin/master hasn't changed since the last pull?

I only want to reorganize history, not overwrite file contents.

Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
  • Why not just not use force push? What do you mean you're "reorganizing" history? –  Jun 28 '14 at 01:10
  • 3
    Point of this question: When trying to rewrite the history, you have to force push to update the remote. However, between the time where you fetched the last version from the remote and rewritten it to when you force push, additional changes could have occurred at the remote. So to be safe, you should fetch again just before you force push to make sure that you don’t overwrite new stuff you haven’t seen before. But the `fetch && push -f` still allows for a (very short) break in which changes could happen. So a single `force-push-but-only-if-remote-is-still-on-commit XY` is desired. – poke Jun 28 '14 at 01:30
  • See also http://stackoverflow.com/a/18505634/6309 and (for recovering a forced push) http://stackoverflow.com/a/20423029/6309 – VonC Jun 28 '14 at 04:24

1 Answers1

7

There is an option called --force-with-lease for git push. Doing

git push --force-with-lease

will do exactly what you desire and only force-update the remote branch if it is still on the same version as your remote tracking branch (i.e. origin/branch).

You can also specify a revision explicitely if you want to check for another version:

git push --force-with-lease=branch:someCommitHash
poke
  • 369,085
  • 72
  • 557
  • 602
  • This interests me. Just to make sure I understand: so as long as you don't fetch while rewriting history you should be okay. i.e. fetching immediately before `--force-with-lease` negates the `with-lease` part (because it might update `origin/branch`). – ta.speot.is Jun 28 '14 at 01:50
  • No, if you rewrite history (in any way) and force push using `--force` you are overwriting whatever is on the remote, regardless of what happened there. Using `--force-with-lease` instead also force pushes and overwrites everything *but only* when nothing happened to the remote branch in the meantime, making sure you don’t overwrite things you weren’t aware of. – poke Jun 28 '14 at 01:59
  • Sure, but if you fetch immediately before using `--force-with-lease` then `origin/branch` is going to be "up-to-date" (even if your rewritten `branch` is not). Which means there are no protections offered by `--force-with-lease` if you fetch. – ta.speot.is Jun 28 '14 at 02:01
  • 2
    That is correct, yes. But when fetching, Git will tell you whether there were any new changes, so you would be aware of anything you overwrite. – poke Jun 28 '14 at 02:02
  • I did not realize this option even existed. I guess I'll have to stop referring to the [official documentation](https://www.kernel.org/pub/software/scm/git/docs/git-push.html), which seems to be out of date in several places, not just with `git push`. –  Jun 28 '14 at 02:37
  • @poke alternatively, instead of linking to [git-scm](http://git-scm.com/docs/git-push), you could also link to the [documentation source code](https://github.com/git/git/blob/v2.0.1/Documentation/git-push.txt), which might be a little easier to read. On second thought, never mind, it's all in a pre-built state, that's no good. –  Jun 28 '14 at 03:01