git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: how to rebase backwards

From
Junio C Hamano <gitster@pobox.com>
Date
Nov 3, 2009, 07:43 UTC
Message-ID
<7vocnkt5o4.fsf@alter.siamese.dyndns.org>
In-Reply-To
<20091103054510.GB7117@debian.b2j>
bill lam <cbill.lam@gmail.com> writes:
Show 8 quoted lines
> I want to rebase a new branch onto an earlier commit 
>
> original:  
> E is a newly created branch from D and not yet modified
>
>                     E
>                    /
> -- A -- B -- C -- D

I sense a grave misconception here. If you have "not yet modified" anything at all since D, then E does *not* even exist.

Remember, a branch is just a pointer pointing at a commit. You can have more than one such pointers pointing at the same commit. So, if you have been working on 'master' branch, building up to D, your history would look like this:

    ---A---B---C---D
                   ^ master
And you would "create a branch", say "hack", like this:
    $ git checkout -b hack
What happens to your history when you do so is this:
                   v hack
    ---A---B---C---D
                   ^ master
The same commit "D", pointed by two branches, 'master' and 'hack'.

If you start editing files at this point, before making a commit, nothing in the history changes. But once you make a commit E while on branch 'hack' (since you ran "git checkout -b hack" above), the history changes into this:

                     E
                    /^ hack
    ---A---B---C---D
                   ^ master
Show 11 quoted lines
> new: what I wanted
>
>      B'-- C' -- E     for deployment
>     /          
> -- A -- B -- C -- D    trunk
>
> so that I can continue to change all commits from B to C without
> affecting E
>
> I try (not sure if correct) doing it by
>   git rebase --onto A B E
This asks to replay C, D and E in this order on top of A, to create
      C'--D'--E'
     /
 -- A
which is different from what you described earlier.

Assuming that you did actually commit to create E, after branching 'hack' off of 'master', i.e. your history looks like this:

                     E
                    /^ hack
    ---A---B---C---D
                   ^ master
the way to create what you want would actually be
    $ git checkout -b deploy master^ ;# branch deploy at "C"
    $ git cherry-pick hack           ;# replay E on top of it
which would make a history of this shape.
                 v deploy
                 E'  E
                /   /^ hack
    ---A---B---C---D
                   ^ master

If you need to later tweak B and C (only) for deployment branch, you could further rewrite B and/or C with

    $ git rebase -i A

to rewrite everything since A leading to the tip of your current branch (i.e. E'), to result in

                   v deploy
           B'--C'--E"
          /
         /       E'  E
        /       /   /^ hack
    ---A---B---C---D
                   ^ master

Now, you may not want to keep both 'hack' and 'deploy'. Perhaps you forked 'deploy' and modified for E but it was done on top of D that you did not want to include in 'deploy' by mistake. IOW, you might have done this:

                     E
                    /^ deploy
    ---A---B---C---D
                   ^ master

Another way to make 'deploy' point at the result of replaying E on top of C when your history looks like this is (assuming you are on 'deploy'):

    $ git reset --hard HEAD^^ ;# reset to "C"
    $ git cherry-pick @{1}    ;# cherry-pick "E"
That would give you a history of this shape:
                 v deploy
                 E'  E
                /   /
    ---A---B---C---D
                   ^ master

Note that the original commit "E" becomes dangling and it will eventually be garbage-collected.

Previous: bill lamNext: bill lam
Message 2 of 5 in “how to rebase backwards”
  1. bill lamNov 3, 2009
  2. Junio C HamanoNov 3, 2009
  3. bill lamNov 3, 2009
  4. David KågedalNov 5, 2009
  5. bill lamNov 6, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.