22

I had a discussion recently with people absolutely opposed to a rebase strategy of feature branches on GIT. It seems to be an accepted pattern to use rebase only for local, private branches but never use it when there's several people working on a same feature & branch, as per this so-called "Golden Rule of Rebasing" (like explained here: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/conceptual-overview )

I am just surprised there's a consensus on this. I worked 3 years with a full rebasing strategy, with about 20 developers working togeteher and guess what, it worked.

The process is basically:

  • You create your feature branch, let's call it "myfeature", and push it to origin/myfeature
  • Other people may check it out and work on it
  • You may sometimes rebase it from master: from "myfeature", git rebase origin/master ; and then, yes, you have to push-force it.
  • What happens when other people want to push their commits? They just rebase it: git rebase origin/myfeature . So they're now in fast-forward and can push it without forcing.

The only principle to respect is that the feature branch is owned by someone. The owner is the only one who can push-force.

So, I admit: as soon as there's a push-force, there's a risk to do errors. That's true. But there's also many ways to recover from errors, and really, in 3 years of development, I didn't saw a lot of force-pushing mistakes, and when it came to happen we always found a way to recover properly.

So, why is this "Golden Rule of Rebase" being so widely accepted? Is there something else I missed with that? I understand it requires a minimum of organization (every strategy requires some organization), but it works.

  • Something I forgot to tell, but it has its importance: in my previous experience we were using gerrit as a code review tool. It means that if someone pushes a commit while the branch owner is doing a rebase, there's no risk that the commit get lost, because it's pushed to gerrit instead of directly to the origin repository. And since branch owner is the only one who has the right to submit commits from gerrit, the risk to make mistakes was very low. – Joel Jun 17 '15 at 15:12
  • what if I merge someone else's feature branch into my own? – Winston Ewert Jun 24 '15 at 14:33
  • If your feature is dependant on another one, then I guess you could rebase yours from the other one: git rebase origin/otherFeature (I say rebase rather than merge, since the goal is to keep the history linear). I admit that the complexity of all that increases a lot when you introduce more and more dependencies between branches. – Joel Jun 24 '15 at 17:25
10

The problem with force pushing isn't about your feature branch and master, but about pushing your master to someone else's master - that synchronization is going to be overwriting their master with your changes, ignoring whatever is on their tip.

Considering this danger, there's a reason why you should not be using it at all unless things have screwed up and you absolutely, totally need to use it to effect repairs. A SCM system should not ever need to be forced like this, if it does its because something went horribly wrong (and my first approach in such cases would be to restore backups and repeat the operations to keep the history intact).

So perhaps the question is why are you rebasing at all? For 'clean' history when bringing features back to master? If so, you're throwing out all the good history concerning branching for purely style reasons. IMHO fast-forward merging is also not a best practice either, you should want to keep all history so you can see what you really did, not a sanitised version afterwards.

  • You could, of course, pull on master, rebase, and then force push, but that is not atomic. – Kevin Jun 17 '15 at 11:41
  • @gbjbaanb you're absolutely right, rebasing strategy is all about style reasons / more readable history. I'm not trying to argue that it's better, or not. But it's possible to do so, and that's the point I want to raise. Of course I wasn't talking about force-pushing on master, but only on feature branches. – Joel Jun 17 '15 at 12:31
  • 4
    IMHO the design feature of both rebase, and fast-forward merges was a mistake. SCM is about keeping the history so you can see what happened when you need to, and take snapshots for relevant points in time. At least that's what most people want, I guess Linus wanted the history to be as simple for him to read as possible and so put them in for his benefit. IMHO he should have put more effort into making diffs between 2 revisions more manageable instead (ie allowing the view to be simpler, not the underlying history) – gbjbaanb Jun 17 '15 at 12:37
  • 2
    When you publish a paper, do you publish the first draft? Is there some law that says the tools you use to write the first draft can't be used to edit it for publication? Git's a development tool. If you want to reliably and verifiably preserve a series, preserve it. If you want instead to edit it for publication, edit it. Git's stellar at both tasks. – jthill Jul 15 '17 at 1:03
5

Rebase isn't essential, as you say it is mostly cosmetic. Sometimes it is a lot simpler then a merge. So it can have some "actual" value, but only "sometimes"

Improper use of rebase can be costly. Unlikely to lose data if you know enough to not panic and look up recovery procedures, but "hey nobody push for a while I have to fix ..." isn't great. Nor is having someone burn time on research recovery and testing when they could have been adding features or squashing bugs (or home with family).

With that trade off the results of "very few people do a rebase and forced push" isn't very surprising.

Some workflows can reduce the risk, for example reduce it to "zero as long as you remember which branches you are allowed to force and which you can't". In reality they might be safe enough to justify the risk, but folks frequently make choices based on larger folklore. Then again in reality the benefits are pretty small, so how tiny does the risk really need to be?

  • 3
    "hey nobody push for a while I have to fix ..." .. sounds like the old days of using Visual Source Safe. I thought git was better than that. – gbjbaanb Jun 24 '15 at 14:54
  • Yep, thus people make rules like "don't play with the sharp tools! (Force push)" So they can avoid treating avoidable wounds! – Stripes Jun 24 '15 at 15:23
  • 2
    @gbjbaanb Yes, Git is better than that - when you use it properly. Complaining about Git being unable to deal with concurrent development elegantly when you are constantly rebasing and changing the commit hashes of everything is like complaining about cars being inferior to carriages because they are much heavier for the horse to pull. It's not the tool's fault that people insist on using it wrong... – Idan Arye Jun 24 '15 at 16:46
  • 4
    Well it kind of is the tool's fault. Git exposes a LOT of sharp edges, and while sometimes notes that they are sharp it frequently does not. If you compare it to say CVS where all the sharp bits are in a SINGLE subcommand ("cvs admin"? It has bene a while...) that goes out of the way to say "this can cut you bad, don't use it unless you have a dire need". Or other version control systems that omit capabilities that can hurt. – Stripes Jun 24 '15 at 17:21
  • 4
    That isn't to say git hasn't made valid design choices (group related functionailaty by subcommand, and prefer allow git to solve more complex things in the right hands)...but they are CHOICES, and one can be critical of the choice to have so many sharp edges, much like one can be critical of the choice of other VCSs to leave out so many useful features "just because someone can get hurt". – Stripes Jun 24 '15 at 17:25
2

To add a different voice:

Yes, if you work as you describe, there is no problem with using rebase and force-pushing. The critical point is: You have an agreement in your team.

The warnings about rebase and friends are for the case where there is no special agreement. Normally, git protects you automatically, by, for example, not allowing a non-fast-forward push. Using rebase and force-pushing overrides that safety. That's ok if you have something else in place.

On my team, we also sometimes rebase feature branches if history has become messy. We either delete the old branch and make a new one with a new name, or we just coordinate informally (which is possible because we are a small team, and no one else works in our repository).


Note that the git project itself also does something similar: They have an integration branch that is regularly recreated, called "pu" ("proposed updates"). It is documented that this branch is recreated regularly, and that you should not base new work on it.

1

So, I admit: as soon as there's a push-force, there's a risk to do errors. That's true. But there's also many ways to recover from errors, and really, in 3 years of development, I didn't saw a lot of force-pushing mistakes, and when it came to happen we always found a way to recover properly.

The reason that Git users tend to avoid shared mutable history is because there is no automatic avoidance or repair of these problems. You have to know what you're doing, and you have to fix everything up manually if you mess up. Allowing exactly one person to do force-push is unintuitive and contrary to the distributed design of Git. What happens if that person goes on vacation? Does someone else temporarily own the branch? How do you know they won't walk all over whatever the original owner was doing? And in the open source world, what happens if the branch owner gradually drifts away from the community, without officially leaving? You could lose a lot of time waiting to hand off branch ownership to someone else.

But the real issue is this: If you mess up and don't immediately realize it, the old commits will eventually vanish after enough time has elapsed. At that point, the problem may be unrecoverable (or at least, potentially very hard to recover, depending on what your backup story looks like -- do you backup old copies of your Git repository, i.e. not just clones?).

Contrast this with Mercurial's Changeset evolution work (which, I should note, is not yet finished or stable). Everyone can make whatever changes to history they like, provided the changesets are not marked public. These amends and rebases can be pushed and pulled with total impunity, no need for a branch owner. No data is ever deleted; the entire local repository is append-only. Changesets which are no longer needed are marked obsolete, but kept indefinitely. Finally, when you mess your history up (which is treated as a normal part of your everyday workflow), there's a nifty command to clean it up for you automatically. This is the kind of UX people expect before they go around modifying shared history.

  • I agree with this "git philosophy" and I also think philosophies can sometimes be hacked :). More seriously, as I stated in the comments, that's now 3 years ago, I was in the particular case of having gerrit as a code-review tool which acted as a de-facto backup tool, preventing such potential dramatic loss. Now I still think rebase is OK when you're sure to "control" a branch. Even in an opensource project, if I'm developing a feature and open a pull request, I "own" that PR, I consider I have the right to rebase its branch, it's up to me not to fuck up my own work during rebasing... (1/2) – Joel Jul 13 '17 at 8:52
  • ... , and if some people wants to bring modification to that PR then I consider they should tell me first, and it's a matter a communication. (2/2) – Joel Jul 13 '17 at 8:52
  • PS: thanks for the Changeset evolution link, that's interesting – Joel Jul 13 '17 at 8:57
  • Actually, rebase is like saying: "let's rewrite all my work from scratch (from latest master), deleting all my previous work.". If you're ok to do that, you're ok to rebase. – Joel Jul 13 '17 at 9:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.