Re: How to switch kernel customizations from 2.6.15.6 to 2.6.16?

5 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: How to switch kernel customizations from 2.6.15.6 to 2.6.16?

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:22

Linus Torvalds [off-list ref] writes:
  Personally, I think the rebase syntax sucks, because the _natural_ way 
  to do it is to just describe the set of commits to rebase the same way 
  we describe all _other_ commit sets: as a "begin..end" sequence.
I'd agree in general, and I am not happy about them.

But I have an excuse.

rev-parse's A..B notation was invented on June 13th (178cb24).
But format-patch was originally posted on May 30th:

	http://article.gmane.org/gmane.comp.version-control.git/4279

before the convenience of rev-parse was invented ;-).
  So I think rebase _should_ work something like this:

	git rebase origin.. [--onto] linus

  ie just giving an arbitrary range.
In addition, both rebase and format-patch does a bit more than
straight his..mine.

    *---x---x---o---o---o---o
     \                      ^mine
      .---.---.---.
                  ^his

We do _not_ want to process all six of his..mine commits when
doing "format-patch his mine" in the above picture, because
upstream might have accepted some of them already, and we filter
them out with git-cherry.  
  This is even more noticeable for "git-format-patch", where
  that insane "<his> [<mine>]" syntax is even worse, for no
  good reason, when again it should really just work like "git
  diff" where giving a single revision implies a single
  revision, and giving a range implies a range, and no strange
  "mine" vs "his" rules ]
Having said that, you have been able to say format-patch A..B
C..D E..F for quite some time (since November 21, 2005).

Rebase is even more strange, especially with --onto.  When you do

    $ rebase --onto his origin mine

in this picture,

    *---x---x---o---o---o---o
     \      ^origin         ^mine
      .---.---.---.
                  ^his

you are discarding two 'x' commits, and lost-found is the only
thing that would help you to recover them.

Unlike format-patch which takes ranges, rebase does not let you
say "rebase --onto base A..B C..D E..F"; what happens might be
too confusing, especially if B, D, F are not coming from the
current branch.  The current branch is rewound to base and then
the chosen sets of patches are applied, which is kind-of scary.
It would feel safer to do:

	$ git checkout -b newbranch base
        $ git format-patch --stdout A..B C..D E..F | git am -3

and after making sure the result is really what you want
resetting the original branch to the current (newbranch) head.

Re: How to switch kernel customizations from 2.6.15.6 to 2.6.16?

From: Linus Torvalds <torvalds@osdl.org>
Date: 2016-06-15 22:42:22


On Tue, 28 Mar 2006, Junio C Hamano wrote:
Having said that, you have been able to say format-patch A..B
C..D E..F for quite some time (since November 21, 2005).
Yes, and the documentation still talks only about the old insane format..
Rebase is even more strange, especially with --onto.  When you do

    $ rebase --onto his origin mine

in this picture,

    *---x---x---o---o---o---o
     \      ^origin         ^mine
      .---.---.---.
                  ^his

you are discarding two 'x' commits, and lost-found is the only
thing that would help you to recover them.
.. and this is largely because the whole interface is broken.

The breakage shows up as inflexibility and having a hard time explaining 
what the thing does.  It shows up as confusion about the usage, and about 
the meaning of a simple command line.

For example, in the most trivial format, doing a

	git rebase <branchname>

the _logical_ thing (from just reading the command) to believe the above 
does is to think that it rebases the named branch. I pretty much guarantee 
that that is what any native English speaker would think it does, if they 
thought about it.

The fact that it actually does the _reverse_, and rebases not the named 
branch, but the branch you are on right now.

The fact that when things go south, the old branch has gotten lost (unless 
you remember about ORIG_HEAD) is all related to the same thing. It's just 
a very non-intuitive interface.

That was fine when people weren't supposed to use it, and it was doing 
something very very special, but that has clearly changed over time. Now 
people are encouraged to use it, it's pretty well-known, and even new git 
users seem to want to do it.

I think "git rebase" is a lost cause. It's just fundamentally a very very 
badly designed command, because it does everything the wrong way around.

I personally believe that the _sane_ way of doing rebasing is to 
 - get rid of "git rebase" entirely
 - teach "git cherry-pick" to take a _range_ of commits instead.

Lookie here, let's look at your example a bit more (which in turn comes 
from the original question that started this thread):

    *---x---x---o---o---o---o
     \      ^origin         ^mine
      .---.---.---.
                  ^his

We have three branch points, and we want to move the commits on "mine" 
from "origin" onto "his". How would you do this so that it's _not_ 
confusing, and so that you can explain to a newbie user what he is doing, 
_especially_ if things go wrong in the middle?

Right now, the sequence is:

	git checkout mine			# if required
	git rebase --onto his origin

and if things go south during the rebase, it's immediately total chaos, 
and you really _really_ need to understand what you are doing.

The above just doesn't make any sense. It's hard to explain why you would 
do something like that.

In contrast, here's an alternate workflow that is much easier to explain, 
and doesn't involve "rebase" at all:

	git checkout his
	git cherry-pick origin..mine

Notice what this does? Show these two sequences to anybody who has some 
basic familiarity with git terminology, but has perhaps never actually 
used it, and ask them what the two sequences do. I pretty much guarantee 
that the second sequence will make sense and get people to generally pick 
the right answer, while the first sequence will make people maybe _guess_ 
the right answer, but it's not intuitive.

In particular, what do you think happens when a patch in the series 
doesn't apply under the two circumstances? Which workflow has the 
"intuitive" way of recovering, and which does not?

Right. The second one has a very intuitive way to recover. In fact, it's 
so intuitive that the answer may be "ok, I'll skip that one commit 
entirely because I don't know how to resolve it, and instead cherry-pick 
the rest, and ask the original author to cherry-pick it for me later". And 
doing so is as easy as

	git reset --hard	# undo the mess from the failed one,
				# the same way we always do for all
				# other failed things

	git cherry-pick next..mine	# do the rest

See? That's a very logical thing to do. It's different from "git rebase", 
but it's different in a _good_ way.

In contrast, the "rebase" conflict resolution is pretty damn esoteric, and 
using a simple "gitk --all" when things go wrong won't help you pick 
things up at all.

Now, "git cherry-pick" doesn't actually support the above format, and I'm 
not saying that the "git rebase" name itself is evil. I think we could fix 
"git rebase" to work better, but the semantics - the way they are 
_designed_ right now - are just horrible.

			Linus

Re: How to switch kernel customizations from 2.6.15.6 to 2.6.16?

From: Linus Torvalds <torvalds@osdl.org>
Date: 2016-06-15 22:42:22


On Wed, 29 Mar 2006, Linus Torvalds wrote:
Right now, the sequence is:

	git checkout mine			# if required
	git rebase --onto his origin
vs
	git checkout his
	git cherry-pick origin..mine
Btw, I realize that the advantage of "git rebase" is that it doesn't 
change somebody elses branch. However, we'd still be a lot better off with 
us simply doing the equivalent of something like

    git checkout -b new-mine his && 
	git cherry-pick origin..mine &&
	git rename-branch -f new-mine mine

instead of what git-rebase does now.

			Linus

Re: Rebase semantic and cherry-pick

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:42:22

Linus Torvalds wrote:
In contrast, here's an alternate workflow that is much easier to explain,
and doesn't involve "rebase" at all:

git checkout his
git cherry-pick origin..mine
[...] 
Now, "git cherry-pick" doesn't actually support the above format, and I'm
not saying that the "git rebase" name itself is evil. I think we could fix
"git rebase" to work better, but the semantics - the way they are
_designed_ right now - are just horrible.
Perhaps if possible also have

git cherry-pick --whole-branch branchname

meaning

git cherry-pick branchname:begining..branchname:HEAD

-- 
Jakub Narebski

Re: How to switch kernel customizations from 2.6.15.6 to 2.6.16?

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:22

Linus Torvalds [off-list ref] writes:
For example, in the most trivial format, doing a

	git rebase <branchname>

the _logical_ thing (from just reading the command) to believe the above 
does is to think that it rebases the named branch. I pretty much guarantee 
that that is what any native English speaker would think it does, if they 
thought about it.
Not really.  Most of the commands in git suite operate on the
current branch.

After thinking about it a bit more, I still agree with you that
things are not as easy to explain as they should be, but I do
not think rebase is so broken anymore.
In contrast, here's an alternate workflow that is much easier to explain, 
and doesn't involve "rebase" at all:

	git checkout his
	git cherry-pick origin..mine
This is _easy_ to explain, yes.  However, I do not necessarily
agree with what you said here:
In particular, what do you think happens when a patch in the series 
doesn't apply under the two circumstances? Which workflow has the 
"intuitive" way of recovering, and which does not?

Right. The second one has a very intuitive way to recover. In fact, it's 
so intuitive that the answer may be "ok, I'll skip that one commit 
entirely because I don't know how to resolve it, and instead cherry-pick 
the rest, and ask the original author to cherry-pick it for me later". And 
doing so is as easy as

	git reset --hard	# undo the mess from the failed one,
				# the same way we always do for all
				# other failed things

	git cherry-pick next..mine	# do the rest
It is not so easy to figure out what the next should be.  If we
limit ourselves to the simplest case that origin is an ancestor
of mine, yes, but in general, no.  We are rebasing presumably
because upstream made independent progress so "origin" would not
be an ancestor of mine anymore; and you are talking about the
generic rev-list syntax next..mine === ^next mine.

"reset --hard" to stop cherry picking is easy.  I do not think
continuing is as easy as you made it sound like.

There was a nontrivial amount of thought went into making the
"rebase" restartable.  Actually, that thought was really for
making the "am" restartable, and the hope was once the user
becomes familiar with how to restart "am", restarting "rebase"
is just as easy because you restart them the same way.  You have
it fall back to 3-way merge (and in the case of rebase, it _can_
fall back to 3-way when the patch does not apply, because all
the blob object names recorded in the intermediate patch format
are from your local repository), you resolve and prepare the
index to be committed, and say "git am --resolved".  We _could_
make "git rebase --resolved" a synonym for "git am --resolved",
because "rebase" being tied to "am" only because the former is
implemented in terms of the latter behind the user _is_
unintiutive.
See? That's a very logical thing to do. It's different from "git rebase", 
but it's different in a _good_ way.
As I said, yes, the part to punt is easy.  But that is different
from being able to continue smoothly.  And if you want to punt
during "rebase", you could just as easily do "git reset --hard
ORIG_HEAD", just like you would punt a failed merge with "git
reset --hard ORIG_HEAD".

The non-English (and no natural language I presume) syntax
rebase takes is a mistake from understandability point of view.
I fully agree with that.  Let me think aloud how we could
rephrase them better.

(1) git rebase origin

         A---B---C master (HEAD)
        /
    ---o---o---o---o origin

    I started building on tip of his but while I was woking on
    it he made independent progress.  I want to rebuild my
    branch as if I started at the tip of his current branch.

                     A---B---C master (HEAD)
                    /
    ---o---o---o---o origin

(2) git rebase --onto origin A..C

         A---B---C master (HEAD)
        /
    ---o---o---o---o origin

    I started building on tip of his but while I was woking on
    it he made independent progress.  I want to rebuild my
    branch as if I started at the tip of his current branch, but
    come to think of it I do not need A anymore.

                     B---C master (HEAD)
                    /
    ---o---o---o---o origin

    I personally feel _this_ form is the most logical, and form
    (1) for the sake of consistency could be spelled as:

        $ git rebase --onto origin origin..master

    So you could think of (1) a convenient shorthand for this
    spelled-out form.

(3) git rebase --onto origin A..C topic

               B---C topic
              /
         .---A---. master (HEAD)
        /
    ---o---o---o---o origin

    I have a topic that interferes with what he did in his
    latest updates, and I'd like to resolve the conflicts
    early.  Currently I am not on that branch so first let me
    switch to it.

         .---A---. master
        /
    ---o---o---o---o origin
                    \
                     B---C topic (HEAD)

    This form was done only as a shorthand to save typing "git
    checkout topic" at the beginning, just like "git checkout -b
    newbranch" can be used to save typing "git branch newbranch"
    before the checkout, but I agree it may have made things
    more confusing.  We _could_ deprecate this form and require
    the user to always switch branches before starting the
    rebase.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help