0

Say I am on a feature branch, and I do:

git fetch origin 
git merge origin/dev

I do that a few times, then a week later I do:

git fetch origin
git rebase origin/dev

what happens to the merge commits I created earlier? Do they get thrown away? I am wondering if rebase can coexist with merge after the fact.

(Note that origin/dev is the integration branch in this case).

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • I’d say they could as rebase would take the base of both the feature and origin/dev branch, take the feature and place on top (above last commit) of the other one. It should not take care of previous history – Mac_W Sep 19 '18 at 18:30
  • Perhaps this will be useful for you? https://stackoverflow.com/questions/15915430/what-exactly-does-gits-rebase-preserve-merges-do-and-why – chevybow Sep 19 '18 at 18:40

1 Answers1

1

Without -p or --preserve-merges, or the newfangled --rebase-merges option, git rebase simply discards merges.

I say "simply" here, and the "discard a merge commit" part is simple, but the overall process is a little complicated. The key is to first read and understand the web site Think Like (a) Git, and sit down and work through a bunch of examples of reachability. Draw some graphs, e.g.:

       G-----H         R   <-- tip1
      /       \       /
...--F---L-----M--N--O--S   <-- tip2
      \               \
       J---K-----------P   <-- tip3

(I left out Q as it looks too much like O. I left out I by accident, oops. :-) ) Which commits are reachable from M, or P, or K? When you can look at this or some other graph and quickly enumerate the reachable commits, you are ready for the next step.

What git rebase does is to enumerate those commits that are reachable from the HEAD commit, excluding commits reachable from the other commit that you name. That is, given git rebase origin/dev, Git finds all the commits that are reachable from origin/dev. These commits are excluded from the rebase, no matter what else might happen.

Then, with the full list of "cannot possibly include these commits", Git makes a list of maybe-included commits. These are the HEAD commit and all commits reachable from the HEAD commit. So if we attach HEAD to the name tip1, for instance, the maybe-included commits are R (to which tip1 points), O (reachable from R), N (reachable from O), M (reachable from N), H and L (both reachable from M), G (reachable from H), F (reachable from both L and G), and any commits before F.

Now that rebase has a list of maybe include and definitely exclude, Git tosses all the definitely exclude commits out of the list. The result is a smaller list "maybe include"s. At this point, a default rebase also throws out all merge commits: commits with at least two parents.

Whatever is left, these are commits with one parent, so Git can run git cherry-pick on them. Git checks out—as a detached HEAD—the --onto commit, or the target commit (origin/dev) if you did not specify --onto, and cherry-picks each commit from that list, one commit at a time. That builds the new chain. Once the chain is built, Git moves the old branch name to the new HEAD commit, and the rebase is complete.

torek
  • 448,244
  • 59
  • 642
  • 775
  • when it discards merges and their respective commits, will git garbage collect them and delete them from disk? –  Sep 19 '18 at 21:33
  • @MrCholo: eventually, yes, provided nothing *else* refers to them: the branch and HEAD reflogs will typically keep them around for at least 30 days, after which they probably become garbage to be collected. Because commits can be on more than one branch, though, rebasing one reference might still leave the commits reachable from some *other* reference. – torek Sep 19 '18 at 21:36
  • If we rebase our local feature branch with remote/integration, do we need to rebase it on all the commits from integration or just the most recent commit from integration? In other words, since commits are usually just pointers to one parent, if I don't need all the other commits locally, is there a way just to rebase onto the one parent from the integration branch on the remote? –  Sep 19 '18 at 22:00
  • @MrCholo: I don't think I understand the problem / question as asked. Can you draw the graph of the current set of commits, and the graph you'd like to have at the end of your rebase process? – torek Sep 19 '18 at 22:17
  • I could explain it on the phone haha, but even if I draw a picture I am not sure I could get the point across –  Sep 20 '18 at 19:19