threads / discuss / 14177

Re: is rebase the same as merging every commit?

Subject: Re: is rebase the same as merging every commit?

## tl;dr

5 messages between Jun 27, 2008 and Aug 14, 2016.

replies: 4people: 3as markdown or json

David Jeske· Aug 14, 2016, 00:43 UTC · lore

is rebase the same as merging every commit?

Rebasing is described in the docs I've read as turning this: (sorry for the dots)

..........A---B---C topic ........./ ....D---E---F---G master

Into this:

...................A'--B'--C' topic ................../ .....D---E---F---G master

If I understand it right (and that's a BIG if), it's the same as doing a merge of C into G where every individual commit in the C-line is individually committed into the new C' line.

...........-------------A---B---C ........../ / / / ........./ /---A'--B'--C' topic ......../ / ....D---E---F---G - master

(1) Is the above model a valid explanation?

(2) From the documentation diagrams, it looks like the rebased A' has only (G) as a parent, not (A,G). If this is the case, why? (i.e. not connecting those nodes throws away useful information)

(3) If it only has (G) as a parent, does the rebase explicitly remove the source A,B,C nodes from the repository? (the diagrams make it look like it does) ..or do they just get cleaned up during GC?

Matthieu Moy· Jun 27, 2008, 06:30 UTC · re: David Jeske · lore
"David Jeske" <jeske@willowmail.com> writes:
Show 22 quoted lines
> Rebasing is described in the docs I've read as turning this: (sorry for the
> dots)
>
> ..........A---B---C topic
> ........./
> ....D---E---F---G master
>
> Into this:
>
> ...................A'--B'--C' topic
> ................../
> .....D---E---F---G master
>
> If I understand it right (and that's a BIG if), it's the same as doing a merge
> of C into G where every individual commit in the C-line is individually
> committed into the new C' line.
>
> ...........-------------A---B---C
> ........../            /   /   /
> ........./        /---A'--B'--C'  topic
> ......../        /
> ....D---E---F---G - master
I'd draw that the other way:
  ...........---------A---B---C
  ........../          \   \   \
  ........./        /---A'--B'--C'  topic
  ......../        /
  ....D---E---F---G - master
> (1) Is the above model a valid explanation?
Sounds correct to me.
> (2) From the documentation diagrams, it looks like the rebased A' has only (G)
> as a parent, not (A,G). If this is the case, why?

Well, one could imagine a "rebase keeping ancestry" command, which would keep A and G (indeed, you can do that by hand with multiple calls to "merge"). The advantage being that further merges involving both A and A' have better chance to succeed.

But philosophy of "rebase" is different: the idea is that you usually rebase your private branches before submission, and the guys you submit to are interested in your changes (i.e. the patch serie diff(G,A'), diff(A',B'), ...), not the way you got this patch serie.

So, discarding this ancestry information is a bit like discarding your *~ files (or whatever backup files your editor might create) after some time: it has been valuable information, but at some point, it becomes noise you don't want to hear.

> (i.e. not connecting those nodes throws away useful information)

For the use-cases where this information is useful, "rebase" is not for you. Indeed, in these cases, a plain "merge" is usually what you want.

> (3) If it only has (G) as a parent, does the rebase explicitly remove the
> source A,B,C nodes from the repository?

Most commands, and this includes rebase, are "add-only". The objects will remain unreferenced and will be pruned by the next git gc --prune. Unreferenced objects do not harm, they just eat your disk space.

Well, that was a first approximation. Indeed, the reflog still references C, see "git reflog". For example, after the rebase, if you realize that you actually didn't want this rebase, you can still "git reset --hard HEAD@{1}" or something like that.

-- 
Matthieu
David Jeske· Jun 27, 2008, 06:50 UTC · re: Matthieu Moy · lore
-- Matthieu Moy wrote:
Show 7 quoted lines
> > (3) If it only has (G) as a parent, does the rebase explicitly remove the
> > source A,B,C nodes from the repository?
>
> Most commands, and this includes rebase, are
> "add-only". The objects will remain unreferenced and
> will be pruned by the next git gc --prune. Unreferenced
> objects do not harm, they just eat your disk space.

I see. So it would be reasonable for the documentation to be altered slightly to show that the original nodes are still there, and that the primary difference between merging those changes one-by-one and rebasing is that rebase does not connect the new to the old. If you want to keep the old, you can toss a branch name on it, and if not, it still lives until the gc timeout.

The current docs showing those nodes missing tells me that they disappear, which is both scarry, and apparently inaccurate.

Petr Baudis· Jun 27, 2008, 08:34 UTC · re: Matthieu Moy · lore
On Fri, Jun 27, 2008 at 08:30:56AM +0200, Matthieu Moy wrote:
Show 36 quoted lines
> "David Jeske" <jeske@willowmail.com> writes:
> 
> > Rebasing is described in the docs I've read as turning this: (sorry for the
> > dots)
> >
> > ..........A---B---C topic
> > ........./
> > ....D---E---F---G master
> >
> > Into this:
> >
> > ...................A'--B'--C' topic
> > ................../
> > .....D---E---F---G master
> >
> > If I understand it right (and that's a BIG if), it's the same as doing a merge
> > of C into G where every individual commit in the C-line is individually
> > committed into the new C' line.
> >
> > ...........-------------A---B---C
> > ........../            /   /   /
> > ........./        /---A'--B'--C'  topic
> > ......../        /
> > ....D---E---F---G - master
> 
> I'd draw that the other way:
> 
>   ...........---------A---B---C
>   ........../          \   \   \
>   ........./        /---A'--B'--C'  topic
>   ......../        /
>   ....D---E---F---G - master
> 
> > (1) Is the above model a valid explanation?
> 
> Sounds correct to me.

I don't think you can call it correct since it assumes !(2) while (2) holds. Drawing the diagram this way is misleading; merging commits one-by-one implies preserving the merge information in the history graph; nothing like that is done by rebase.

Rebase is more like _cherry-picking_ all the patches on your branch on top of the upstream branch. You just essentially take each patch (commit message + diff to parent) growing on top of upstream's E and recommit it on top of G.

> > (2) From the documentation diagrams, it looks like the rebased A' has only (G)
> > as a parent, not (A,G). If this is the case, why?
..snip..
Show 5 quoted lines
> > (i.e. not connecting those nodes throws away useful information)
> 
> For the use-cases where this information is useful, "rebase" is not
> for you. Indeed, in these cases, a plain "merge" is usually what you
> want.

Indeed, noone forces you into the rebase workflow for your own projects. I personally never ever rebase (I do use StGIT though, but it records per-patch history and makes sure I'm always in some consistent state).

-- 
				Petr "Pasky" Baudis
The last good thing written in C++ was the Pachelbel Canon. -- J. Olson
David Jeske· Aug 14, 2016, 00:43 UTC · re: Matthieu Moy · lore
-- Matthieu Moy wrote:
Show 7 quoted lines
> > (3) If it only has (G) as a parent, does the rebase explicitly remove the
> > source A,B,C nodes from the repository?
>
> Most commands, and this includes rebase, are
> "add-only". The objects will remain unreferenced and
> will be pruned by the next git gc --prune. Unreferenced
> objects do not harm, they just eat your disk space.

I see. So it would be reasonable for the documentation to be altered slightly to show that the original nodes are still there, and that the primary difference between merging those changes one-by-one and rebasing is that rebase does not connect the new to the old. If you want to keep the old, you can toss a branch name on it, and if not, it still lives until the gc timeout.

The current docs showing those nodes missing tells me that they disappear, which is both scarry, and apparently inaccurate.

← back to recent threads