2

I'm new to Git, having worked with TFS for nearly 20 years, and I'm currently trying to get my head around "rebase". I broadly understand what it's doing, but there are a couple of caveats/warnnings that I keep seeing, but I don't really understand them:

"don't rebase after pushing" So if I've rebased my master branch then pushed those changes to the remote repo, at what point is it safe to rebase master again? After the next pull?

"don't rebase on a public branch" what exactly do they mean by "public"? I have a "master" branch in both my local repo and the remote repo. Are they saying I can't rebase on either master branch or just the remote branch?

An explanation and/or example to clarify what is meant here would be brilliant. Obviously the other option is to simply avoid using rebase altogether in the team, with us all being Git novices.

3
  • A change is public if someone has fetched it. The answer will depend on whether the repo on your machine is accessed by your team, or you only go via a central location
    – Caleth
    May 19, 2023 at 14:25
  • 2
    is to simply avoid using rebase altogether in the team, with us all being Git novices Unless you are all experts or well-versed in git, I would still advise against rebasing branches no matter how expert you or half of the team is. It only takes one of you to cause the chaos.
    – Laiv
    May 19, 2023 at 15:44
  • 2
    Not using rebase is fine until you learn more about it. Some people never use it. May 19, 2023 at 21:46

4 Answers 4

11

Rebasing is a red herring here. The real problem is "rewriting history". More precisely, it is "rewriting history that others have already built upon". Rebasing is simply one way of rewriting history in Git, but it is far from the only one.

Rewriting history causes problems for anybody who has already pulled the changes, added their own commits on top, and doesn't expect the history to change.

As you can see, there are three necessary conditions for history rewriting to become an actual problem:

  1. The history "escapes" your "sphere of influence".
  2. People commit on top of the history.
  3. People are surprised by the rewrite.

If only one of those conditions does not apply, then there is no problem:

  1. If you only rewrite private history, no-one will ever notice.
  2. Rewriting the history of a "read-only" branch is fine.
  3. If it is clear beforehand that the history will be rewritten and ideally, this happens with enough warning at a predictable point in time, then people can prepare themselves.

In the past, the Git project itself used to regularly rebase the pu branch. This was a widely-published, public branch, so according to both of your rules, rebasing it would be forbidden. And yet, it was regularly done, and it didn't cause any problems. Why? Because it was documented that this branch would be rebased regularly, and moreover, it was documented in advance, when, and under what conditions, the rebase would happen.

In other words: if you want to rewrite history, you need a conspiracy. Just like in the real world.

2
  • 1
    Yep. Very pragmatic. PS: pu lives on as next. May 19, 2023 at 21:45
  • Great answer! This is a minor nitpick, but I believe in Gitworkflow, pu, and now next and/or seen, are actually "rewritten" as opposed to "rebased". The idea is that they are periodically reset to main to start fresh. The old commits on those branches are thrown away and so technically aren't actually rebased.
    – TTT
    Nov 6, 2023 at 20:28
4

This really comes down to a definition of "safe" and "public"

Safe

It is said that it is "unsafe" to push to a branch after rebasing. In practice it means that, if the following scenario occurs:

  • Developer A pushes a branch.
  • Developer B pulls the branch.
  • Developer A rebases the branch.
  • Developer A pushed the branch again (in practice this would need to be a force push).
  • Developer B pulls the branch again.

Developer B will have to do work, to fix their local history, either:

  • Just update their local branch - if they don't have any commits.
  • Repeat the rebase with their local history to place their new commit at the end of the new rebased history.

Public

Because you create work for other people when the previous scenario occurs, it is generally frowned upon to rebase history that other people have access to. For example a major open source project, probably wouldn't rebase their history.

However if you are:

  • Working closely with another Dev.
  • On a shared branch that only the two of you use.
  • And you agree on / co-ordinate a rebase.

Then there really isn't a downside.

In Practice

If you do "screw up" and create a historical mess locally. It's usually fairly easy to fix.

  • Create a new branch with the code you want on it.
  • Get a fresh copy of master from the remote repository.
  • Make sure your local master points to the same commit as the remote master.
  • Rebase your local changes onto the end of the master.

This will force you to resolve all the merge/rebase conflicts yourself - so others don't have to.

You can now push this clean history either to the master branch or create a new branch for others to use.

--

A simple rule of thumb is: Don't "force push" to the remote repository. In that your can use rebase as much as you like locally (you can only hurt yourself) since git will always prevent you from damaging the public history, if you only every push without "forcing" it.

A push with --force is effectively an overwrite, if you push without --force it is always an append (to the history) - which is why it is considered safe.

1
  • 2
    "For example a major open source project, probably wouldn't rebase their history." – A counter-example is Git itself. Git, at least in the past, used to rebase the pu branch after every release. However, this was not a problem because the fact that this was happening was documented and known to all developers, so they were prepared for it. The problem really only occurs if you rewrite published history and developers aren't prepared for it. May 19, 2023 at 15:37
3

Git rebase is a surprisingly large topic. And just the command itself can take a while to learn to become comfortable with. And then after that you have to consider the social aspect of it (like you are doing). So let’s simplify things so that we can discuss a strategy for rebasing which is, I would claim, very safe.

Prerequisite: do you need it?

Git rebase is an elegant tool, but it is also optional. You don’t strictly need it.

Rebasing as an individual contributor on your feature branches

You can use rebase to rewrite your own branches during development and before merging into mainline.

In the first phase of development your branch might be private. Then rebasing is not a problem since the history has not been shared. So rebase as much you need.

This doesn’t just mean to tidy up your history but also to rebase on top of updates to the main branch (the merge alternative is to merge mainline into your own branch periodically).

The next phase might be the pull request phase. Here some care and consideration is warranted. As you gain experience you can be more flexible at this point. But as a relative beginner you can follow this rule:

  • Don’t rebase after you have published the PR

Note that this is only a temporary disabling of this feature (see next point). So you can still make (what are called) “fixup” and “squash” commits (read man git rebase). But you don’t use rebase yet, just in case reviewers are checking out your branch.

Like already mentioned, the merge-variant of updating your branch according to the main branch is to merge main into your own branch periodically (a “back merge”). This might be necessary if your pull request ends up living for more than a week.

The final phase is the pull request approved phase. Now you can rebase your branch again. Why? To clean up your history. And why is it okay to do so? Because your team has decided that your changes can be merged into mainline; it’s about to be merged in (by you) and so it will be deleted soon and will not matter to anyone.

One precaution to this, though: some people might have based their work on top of yours (they should have told you about this beforehand, by the way, so you should be in the know (or else it’s on them)). It might be easier for them to continue their work if you merge into the main branch directly instead of rebase + merge, since they will need to update their branch to main (their new base). I have no experience with this particular scenario so I can’t say for sure.

So rewriting history before merging into the main branch is generally fine.

Postscript: on rewriting published-but-solo branches

The aforementioned strategy is meant to be simple and straightforward and to avoid arguments and headaches caused by “you changed the branch out from under me”.

Again, as you gain more experience you can be more flexible. Is “public history” really sacred? No, not at all; you might have a tacit understanding that, say, branches in pull requests are owned by the author and not something that other people are supposed to base their own work on willy-nilly. And in that case the contributor has the freedom to rewrite their pull request branches at will.

Postscript 2: People who cannot rebase

This has covered a possible workflow for an individual contributor. Individual contributors have the most freedom when it comes rewriting history since they are often leafs in the development graph. People who practically cannot use rebase are the “integrators” (in Git SCM-speak), or perhaps more commonly known as “maintainers”, since there might be hundreds or thousands of people who are doing development based on their trees (their histories).

2

If you rebase some commits onto another branch you make a copy of those commits. The copies are not the same commits. The original commits still exist; if nobody is using them, they can get garbage-collected eventually.

For example you may rebase the commits D and E onto Q instead of C. This creates new commits D' and E' and makes your current branch (let's say it's master) point to E' as the latest commit on the branch:

A ---> B ---> C ---> D ---> E <- your old master
  \
   --> Q ---> D' --> E' <- your new master

If someone else has made commits coming after your commits they'll also have to rebase theirs onto your copies to keep up:

A ---> B ---> C ---> D ---> E <- your old master
 \                     \
  \                     --> F <- Fred's branch
   \                 what if Fred doesn't rebase?
    -> Q ---> D' --> E' <- your new master

Eventually Fred wants to get his changes into origin/master and so do you. Both D and D' get are going to get merged into origin/master. Is that a problem? Well, maybe. If they are identical, the merge will probably happen automatically, though you'll still have two identical commits in the commit history. If you change D' there are likely to be merge conflicts. If it's just one duplicated commit you can probably work it out, but the more stuff gets duplicated, the harder it is to untangle.

If Fred rebases his commit F onto D' then there's no problem because Git knows that D' and D' are the same commit.

Pushing and pulling, public and private branches are all irrelevant except insofar as they mean more people have seen the commits you are rebasing and possibly made their own commits based on them, which is what really matters. If you are a closed team you may be able to go around and tell everyone that you're about to rebase something; if it's a public project you don't know if anyone checked it out in the mean time - though if it's only been public for a short time, you can hope for the best and wait to see if someone complains about it.

2
  • Not just differences between D and D', any difference between B, C, D and Q, D'
    – Caleth
    May 19, 2023 at 14:22
  • 1
    @Caleth well, I presume B, C, D and Q are pretty much different commits which is why I gave them different letters, but yes, if B or C or D conflicts with Q then you'll have to solve merge conflicts if you merge them both, but this has nothing to do with the rebase
    – user253751
    May 19, 2023 at 14:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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