From: Mike McCormack <hidden> Date: 2016-06-15 22:42:16
Hi,
git-rebase was a very useful tool for me to help organize my patches.
Recently, it seems the behaviour of git-rebase changed. It used to take
the commits I'd made to my "master" branch and reapply them to a new
"master" branch on top of "origin". Where rebase from git-0.99.x used
to work, git-1.1.3 now does nothing and gives me the following message:
git-rebase origin
-> Current branch refs/heads/master is up to date.
However, I can do the "rebase" manually with:
git branch master-20060117
git reset --hard origin
git-format-patch -k --stdout --full-index origin master-20060117 | \
git am --binary -3 -k
Is this broken, or am I meant to be doing something different now?
thanks,
Mike
From: Junio C Hamano <hidden> Date: 2016-06-15 22:42:16
Mike McCormack [off-list ref] writes:
git-rebase origin
-> Current branch refs/heads/master is up to date.
However, I can do the "rebase" manually with:
git branch master-20060117
git reset --hard origin
git-format-patch -k --stdout --full-index origin master-20060117 | \
git am --binary -3 -k
Is this broken, or am I meant to be doing something different now?
What does "git-merge-base master-20060117 origin" give you? If
it is the same as "origin", then the master-20060117 has been
merged with origin, and rebase does not run in this case.
Here is the simplest example:
1---2---3---4 master
/
origin 0
Of course, you _could_ extract patches #1, #2, #3, and #4
between origin and master, and apply them on top of #0 to
reconstruct "master" as you found out, but there is not much
point doing so.
Rebase changes the "master" branch when the development track
between you (master) and upstream (origin) have forked:
1---2---3---4 master
/
origin' 0---5---6 origin
In this case, things are rearranged by rebase:
1'--2'--3'--4' master
/
origin' 0--5--6 origin
End of on-topic answers.
BTW, what this means is that it would not rearrange something
like this:
2---3
/ \
1---4---5---6 master
/
origin 0
But a structure like this could be rebased:
2---3
/ \
1---4---5---6 master
/
origin' 0---7---8 origin
to produce something like this:
1'--2'--3'--4'--6' master
/
origin' 0---7---8 origin
The ordering of patches may turn out to be wrong; #4 might
conflict with already applied #2 and #3. In general, rebasing
such a merged structure is highly discouraged. I think there
was a discussion on this topic on the list recently, and a short
summary was: "if you do a merge, do not rebase; if you are going
to rebase, do not merge". The thread is this one:
http://thread.gmane.org/gmane.comp.version-control.git/14308
Especially please look at a couple of message from Linus:
http://article.gmane.org/gmane.linux.kernel/365410http://article.gmane.org/gmane.linux.kernel/365409http://article.gmane.org/gmane.linux.kernel/365501
I guess we could decompose the commit ancestry chain in such a
case, and reproduce something like this:
2'--3'
/ \
1'--4'--5'--6' master
/
origin' 0---7---8 origin
Rebase has never done this, though. It is left as an exercise
for the reader ;-).
From: Mike McCormack <hidden> Date: 2016-06-15 22:42:16
Junio C Hamano wrote:
Rebase changes the "master" branch when the development track
between you (master) and upstream (origin) have forked:
1---2---3---4 master
/
origin' 0---5---6 origin
Well, I thought I was in the above situation, but it seems that "origin"
has been merged into "master" :/
The "pull, rebase, commit, commit, send patches, pull, ..." strategy
used to work for me, but now it doesn't.
> summary was: "if you do a merge, do not rebase; if you are going
> to rebase, do not merge". The thread is this one:
I want to do rebases. So is it that behaviour of "git pull" that has
been changed to do merges, and I should be using "fetch" instead of
"pull" or something similar?
Mike
btw. I'm not the only person having this problem. Others using the same
commands, and upgrading GIT have run into it too, so something has
changed...
From: Martin Langhoff <hidden> Date: 2016-06-15 22:42:16
On 1/17/06, Mike McCormack [off-list ref] wrote:
> summary was: "if you do a merge, do not rebase; if you are going
> to rebase, do not merge". The thread is this one:
I want to do rebases. So is it that behaviour of "git pull" that has
been changed to do merges, and I should be using "fetch" instead of
"pull" or something similar?
Now, I have realised that a simple mistake (merging from origin in you
scenario) would lead git-rebase to discard earlier patches during the
rebase. If you had a single commit *after* the merge, git-rebase would
have rebased that single patch, and dropped earlier patches.
git-rebase should refuse to run in the above scenario. Is there a
straightforward way to ask if the merge base is "shared"?
<thinking>
If the commit following right after the merge base on "our" side is a
merge commit, there's a good chance we're about to fuck up. To make
double sure, we can walk up that commit to the other parent (the one
that is not the merge base for the current merge) and get what merge
base between that commit and the current merge base. If it returns
anything interesting, we bail out if we are conservative -- or walk up
the history again if we take a more adventurous approach.
If it returns empty, it's a splice merge and get outta here -- you are
not supposed to rebase a splice merge. And if the merge after our
original merge base was an octopus, die too. Those are not rebasable
either.
</thinking>
So, the conservative (and easy) approach would be to make rebase bail
out when it finds any merge commit.
cheers,
martin