Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use rebase if it forces you to stay local?

Tags:

git

I'm sorry for bringing up the philosophical debate about merge vs rebase, but I have a practical question, regarding a typical company workflow (not an opensource project workflow, which might be different).

Rebasing, as pointed here, should not be used if you have pushed your changes. This is so, because others may have branched from your branch, and then rewriting history of that branch (via force-pushing) will make it hard for them.

So the proper way to use rebasing is by committing only locally. But at least in my brief experience that's not desirable:

  • what if your computer gets stolen?
  • what if you lose data due to a disk failure?
  • what if you have to work from two locations (like this person)

Keeping a feature branch local is something counter-intuitive for me. Not only due to the above points, but also due to the following use-case: you are working on a feature, but either get dragged to something more urgent, or go on holiday, or fall sick. A colleague has to complete it. Then you rebase and push (unless you are sick, in which case it stays local and nobody can complete it), and the other person completes it.

During that period there are changes in master. But the other person is already based on a remote branch, so he should either use merge, or rebase and force-push (which, again, might screw things if other people have based their branches on that one meanwhile).

These may sound like edge cases, but they aren't. At least one of these conditions (work from home, falling sick, going on holiday, finishing someone else's work, etc.) happens rather often.

So, is using "rebase" a good way to go in these usecases, or merging (with the additional "merge commits") is the safer and more straightforward option?

like image 606
Bozho Avatar asked Jun 08 '16 13:06

Bozho


Video Answer


2 Answers

So I tend to favor rebasing. Git graph history is important. You want it to have some information about feature branches and how they get merged, but once you have more than a few people, the graph quickly gets into a mess. It's quite often that you would like to get a sense of what happened in the last few days, and the quality of the graph is the difference between being able to get that information from the git graph or not.

Also, note that force pushing feature branches is not that big of a deal. The problem with force pushes is that you have to notify people about git activity via non-git means – ping them on Slack, etc. This obviously doesn't work for an open source project or a branch with multiple contributors. But most feature branches have a single contributor, so they can force push as much as they want. Even if there are two or three people working on it, you can solve it by force pushing rarely – the typical for our organization is before opening a pull request and before merge. You occasionally do it in the middle of the work to get something from upstream, but normally you don't need to unless you want to.

When we merge, we do two things – we rebase on top of master and then we merge with --no-ff. This creates a merge bubble with an empty left path, which (1) groups commits together and (2) makes commits that went directly into master stand out (those are occasionally valid – hotfixes, small improvements, typos, whitespace, etc.).

The caveat of this approach is that it takes a while to learn. You can't use the GitHub merge button (it does not do what we expect) and you have to have enough git chops to do a rebase and pay attention to the graph. Most developers I've met are not there. Every new team member takes a while to grok this and usually messes the history up once or twice (we have git hooks that help). But I've found the tradeoff to be worth it big time. The benefits are:

  • Feature branches are not local.
  • The history is kept pretty clean.
  • Topical commits are grouped via a merge bubble.
  • Force pushing is not usually a problem, because (1) it happens seldom and (2) you either work alone or at most in a pair.

As a sidenote, "don't rebase things you have already pushed to origin" always sounded like a newbie rule for me. Yes, you can mess up big time when you don't know what you're doing. But once you get proficient in git, it's time for the training wheels to come of.

like image 161
Stefan Kanev Avatar answered Sep 30 '22 10:09

Stefan Kanev


The precisely stated rule is: "do not rebase a branch which could be a base for another branch". Usually, you could easily achieve it only by not publishing your branch - no one sees it, so no one could use it. So that's why "should not be used if you have pushed". But in some situations it is acceptable workflow - rebase/push/rebase/push/... You just need somehow agree with others that they do not use the pushed branch for their needs or explicitly agree on a rota who is rebasing/pushing next (in case of sickness/holiday/etc), or if you just working from several locations (I hope you could agree with yourself at some point).

BTW, there is a --force-with-lease option to avoid some harm which could be caused by pushed rebases.

like image 26
kan Avatar answered Sep 30 '22 10:09

kan