4

There's a lot of git questions on the safety of rebase and there seems to be consensus that as long as you remember that rewriting public history is rude, you should be safe, i.e. if none of the commits you haven't pushed to the repo from which you are pulling, you are safe.

However there is this one answer that gives me pause:

https://stackoverflow.com/a/2597107/1339987

Commit to a branch. Push. Merge up to another branch (say you're maintaining two baselines, a patch branch and a new-development branch). Realize other commits have been pushed to the server branch yours is tracking. pull --rebase. Suddenly you've re-made each of the commits against the new hash - and destroyed the merge commit.

I tried playing with this but was not able to reproduce the scenario in question (I may need to create a more complicated merge but have failed to do so thus far). So I am asking for an explanation of this scenario and ideally a set of criteria under which I can safely and relatively mindlessly rely on rebase pulls.

Community
  • 1
  • 1
djechlin
  • 59,258
  • 35
  • 162
  • 290

3 Answers3

4

The scenario in question is in fact possible, but the ramifications are not as severe as you might have been led to believe. Once something is committed in git, you cannot lose that work for 30 days (by default, configurable by git config gc.reflogexpireunreachable) at minimum.

If the scenario above happened and you detected it, you can always revert to the previous tip of that branch prior to the rebase. You can find this tip by looking at git reflog or specifying a time in your checkout like: git checkout 'HEAD@{5 minutes ago}'.

In my years of using git, I've never used git pull --rebase because the pull command in general operates at a higher level than I prefer to think at. I prefer to do the equivalent:

git fetch origin
git rebase -i origin/branch

The explicit branch name and the interactive option on git rebase mean that I am always aware of what is being rebased. Occasionally, when I do the wrong thing, I am surprised and find a gigantic list of commits in my rebase editor.

Also, when I'm working on a short or perhaps medium term feature, I almost always rebase locally, rather than merging upstream changes. This makes my changes clearer to me and simplifies the history when I do eventually push them to the central repository.

So, in summary, the command is as safe as any other git command, but you need to understand what it will do and how it will do it to not end up in an unexpected situation.

Also note: git rebase has an option to attempt to preserve merges. It doesn't look like there's a simple way to specify that with git pull --rebase.

djs
  • 4,626
  • 2
  • 28
  • 38
2

History rewriting is rude if the history is public already. If the changes are local, there is nobody to be rude to.

If you did change something, and a git pull isn't just fast forward, you get a merge, and thus a somewhat messier history. If your changes aren't done yet, I'd prefer to use git pull --rebase to keep history clean (and incorporate upstream changes).

Be careful, any history rewriting creates commits that never existed before, and that thus haven't been read/tested.

vonbrand
  • 11,412
  • 8
  • 32
  • 52
0

This is essentially how gerrit functions. Only authorized users push to the actual repo; most just push to the gerrit review server and let gerrit do the merging. Eventually, when you pull, you get the "centralized" version of the repository, and the related repo tool takes care of always rebasing your branches instead of merging.

In this model, users always pull with rebase. It's worked well for Android so far.

nneonneo
  • 171,345
  • 36
  • 312
  • 383