How to rebase pushed branches without ruining tree?

一笑奈何 提交于 2020-05-17 06:22:45

问题


I'm the only developer working in a repository, so there's no issue with ruining peoples' flow. However when I rebase locally and then try and push it to Bitbucket, it comes back telling me I need to pull the latest changes. I do that, and the rebase has completely ruined my clean tree.

Is there a way to push a rebase to the server without then having an additional "Merge branch" commit as part of it?

Thanks!


回答1:


Rebase is fundamentally a "copy some commits, then discard the old commits in favor of the new and supposedly improved commits" operation.

Consider, for instance, this situation:

...--A--B--E--F   <-- master
         \
          C--D--G   <-- feature (HEAD)

You've finished your feature feature, but for whatever reason, you had to go create two commits on master while you were working. So now feature could stand to be re-written.

No commit can ever change, so it's not actually possible to replace C with a new-and-improved variant, but we can make a new-and-improved C' to replace C anyway, using a temporary branch or Git's "detached HEAD" mode:

                C'  <-- HEAD
               /
...--A--B--E--F   <-- master
         \
          C--D--G   <-- feature

Commit C' does to commit F what commit C does to commit B. The old (and now lousy) C has B as its parent, while the new improved C' has F as its parent. So now we need to copy D to a new-and-improved D', and then do the same again for G:

                C'--D'--G'  <-- HEAD
               /
...--A--B--E--F   <-- master
         \
          C--D--G   <-- feature

We're now ready for git rebase's last trick. It peels the name feature off of commit G and make feature point to G' instead:

                C'--D'--G'  <-- feature (HEAD)
               /
...--A--B--E--F   <-- master
         \
          C--D--G   [abandoned]

Since we can't even see the abandoned commits, in the local repository on your laptop, it looks as though history has always been this way: that you wrote commit C' based on F, and so on. The hash IDs look random; no one but you will ever know about all this.

Only ... you did a git push of commits C-D-G, or at least some of them, to Bitbucket. They have your old-and-lousy commits, pointed-to by their branch name feature. You send them your shiny new ones—git push origin feature—and at the end of this, your Git asks them politely to move their feature name to point to commit G' instead of G.

This would, of course, cause them to abandon commit G in favor of the new and improved G'. That's what you want them to do. But they will say: No, if I do that, I'll lose my precious commit G!

All you have to do is tell them—or have your Git tell them—yes, I know you could lose some commits, but do it anyway! That is, instead of a polite request, you have your Git send them a forceful command.

The way you do this is to add --force or --force-with-lease to your git push command. That turns the polite request, Please, if it's OK, set your feature to a command: Set your feature!

The difference between --force and --force-with-lease is that the latter adds a safety check first. Instead of just saying Set your name feature to point to commit G'!, your Git will say: I think, based on my information, that your feature points to commit G. If so, set it to point to G' instead. If not, let me know that I goofed.

The safety check is obviously usually good, but it's also unnecessary if you're the only one who ever puts new commits into the repository over on Bitbucket.



来源:https://stackoverflow.com/questions/60199314/how-to-rebase-pushed-branches-without-ruining-tree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!