{"thread":{"id":"49725","subject":"using --force-with-lease after git rebase","startedAt":"2018-10-31T19:13:22Z","lastAt":"2018-11-01T01:20:02Z","messageCount":3,"participants":["Alexander Mills","brian m. carlson","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"362121","messageId":"CA+KyZp5Zv77idtpu9jtxDUyE9zPP8UN3LsQBG=M5yM2cnMFgVQ@mail.gmail.com","threadId":"49725","inReplyTo":null,"subject":"using --force-with-lease after git rebase","fromName":"Alexander Mills","fromEmail":"alexander.d.mills@gmail.com","sentAt":"2018-10-31T19:13:06Z","receivedAt":"2018-10-31T19:13:22Z","isPatch":false,"sender":{"key":"alexander.d.mills@gmail.com","avatar":"https://gravatar.com/avatar/8accf19b85aa1020f85582e1f001860f853ce55767c226545a0825a2fcd99f04?d=mp&s=160"},"body":"I have been confused about the need for --force-with-lease after rebasing\n\nImagine I have a feature branch:\n\ngit checkout --no-track -b 'feature' 'origin/dev'\ngit push -u origin feature\n\nI do some work, and then I rebase against origin/dev to keep up to\ndate with the integration branch.\n\ngit fetch origin/dev\ngit rebase origin/dev\n\nthen I try to push to the remote\n\ngit push origin feature\n\nbut that is rejected, I have to do:\n\ngit push --force-with-lease origin feature\n\nwhy is that? Why do I need to force push my feature branch to the\nremote tracking branch after rebasing against the integration branch?\n\n-alex\n\nrelated question:\nhttps://stackoverflow.com/questions/52823692/git-push-force-with-lease-vs-force/53042745#53042745\n\n\n\n-- \nAlexander D. Mills\n¡¡¡ New cell phone number: (415)730-1805 !!!\nalexander.d.mills@gmail.com\n\nwww.linkedin.com/pub/alexander-mills/b/7a5/418/\n"},{"id":"362138","messageId":"20181101005811.GB731755@genre.crustytoothpaste.net","threadId":"49725","inReplyTo":"CA+KyZp5Zv77idtpu9jtxDUyE9zPP8UN3LsQBG=M5yM2cnMFgVQ@mail.gmail.com","subject":"Re: using --force-with-lease after git rebase","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-11-01T00:58:11Z","receivedAt":"2018-11-01T00:58:20Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Wed, Oct 31, 2018 at 12:13:06PM -0700, Alexander Mills wrote:\n> I have been confused about the need for --force-with-lease after rebasing\n> \n> Imagine I have a feature branch:\n> \n> git checkout --no-track -b 'feature' 'origin/dev'\n> git push -u origin feature\n> \n> I do some work, and then I rebase against origin/dev to keep up to\n> date with the integration branch.\n> \n> git fetch origin/dev\n> git rebase origin/dev\n> \n> then I try to push to the remote\n> \n> git push origin feature\n> \n> but that is rejected, I have to do:\n> \n> git push --force-with-lease origin feature\n> \n> why is that? Why do I need to force push my feature branch to the\n> remote tracking branch after rebasing against the integration branch?\n\nWhen you perform a push to an existing branch, Git checks to make sure\nthat the push is a fast-forward; that is, that your changes are a strict\nsuperset of the commits that are in that branch.  When you rebase a\nbranch, you rewrite the commits and their object IDs (their hashes).\nSince you've rewritten some of the commits that were on the version of\nyour branch that you pushed to the server, the commits you want to push\nare no longer a strict superset, and Git requires a force push.\n\nThis provision is in place to prevent data loss.  For example, if you\nand a colleague are both collaborating on a branch that isn't rebased,\nyou would want to avoid pushing changes that overwrote those that your\ncolleague had made.  Git making your push fail is its way of helping\nyou realize that there are changes you have not included and making you\ndecide how you want to handle them.\n\nYou strictly do not need to use --force-with-lease; you could just use\n--force instead.  But using --force-with-lease over --force when\npossible ensures that you are overwriting what you think you're\noverwriting, and not additional working changes that someone else has\nmade, so it's a good practice.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"362139","messageId":"xmqqr2g5vbk4.fsf@gitster-ct.c.googlers.com","threadId":"49725","inReplyTo":"CA+KyZp5Zv77idtpu9jtxDUyE9zPP8UN3LsQBG=M5yM2cnMFgVQ@mail.gmail.com","subject":"Re: using --force-with-lease after git rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-01T01:19:55Z","receivedAt":"2018-11-01T01:20:02Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alexander Mills <alexander.d.mills@gmail.com> writes:\n\n> I have been confused about the need for --force-with-lease after rebasing\n>\n> Imagine I have a feature branch:\n>\n> git checkout --no-track -b 'feature' 'origin/dev'\n> git push -u origin feature\n>\n> I do some work, and then I rebase against origin/dev to keep up to\n> date with the integration branch.\n>\n> git fetch origin/dev\n> git rebase origin/dev\n>\n> then I try to push to the remote\n>\n> git push origin feature\n>\n> but that is rejected, I have to do:\n\nThis all depends on how the \"dev\" branch at the \"origin\" remote\nrelate to the branch at \"origin\" you are updating with the commit at\nthe tip of the \"feature\" branch.  Are you pushing to \"feature\" branch?\n\nIf so, then the rejection is very much expected.  At this point, the\nhistories of the \"feature\" branch at the \"origin\" remote is seeing\nwould look like this:\n\n    ---X---o---o---o---o---A\n        \\\n         x---x---x---x---B\n\nwhere (X) is where you started the old iteration of the \"feature\"\nbranch forking off of the \"dev\" branch, (A) is the tip of that old\niteration of the \"feature\" branch, and (B) is the tip of the new\nitertion of the \"feature\" branch you are trying to update with.\n\nThe \"origin\" repository does not know WHY B is not a fast-forward of\nA.  The only thing it knows is that you are discarding the work done\nin commits (o) while attempting to publish commits (x).  If it is\nintentional, then that's fine, but it does not know (x) are\nreplacements for (o) due to rebasing, so it errs on the side of the\ncaution.\n\nWith the \"--force-with-lease=feature:A\" option, you can tell the\nother side: \"it is OK if this push does not fast-forward, as long as\nI am updating from A\" [*1*].\n\n\"--fore-with-lease\" without saying what the commit you are expecting\nto discard makes Git on the sending side _guess_.  Depending on what\nyou do locally, it can make a wrong guess, so I would not recommend\nsuch a use, but if you saw it succeed and if you did not lose\ncommits at the \"origin\", then it may have guessed correctly ;-)\n\n\n[Footnote]\n\n*1* Telling what the value of 'A' is to the other side is important,\n as you are essentially saying that 'B' has everything you want to\n resurrect from 'A'.  Imagine that somebody else pushed to update\n \"feature\" at the \"origin\" remote from 'A' to 'C' (or if you did so\n and forgot about it) and then you tried to push 'B' after rebasing.\n\n                             C\n                            /\n    ---X---o---o---o---o---A\n        \\\n         x---x---x---x---B\n\n As far as you (who rebased) were concerned, 'B' is equivalent to\n (or \"an improved version of\") 'A' and you want the push that does\n not fast-forward to go through to replace 'A' with 'B'.  By telling\n \"I am replacing A with B\" (instead of saying \"I am replacing\n whatever with B\", which is what \"--force\" is), the receiving side\n at the \"origin\" repository can notice that there was another update\n by somebody else's push to the branch while you are preparing 'B'\n and the tip of \"feature\" is no longer at 'A', and reject the push\n in order to prevent you from losing the work between 'A' and 'C'.\n"}]}