Git: How to rebase to a specific commit?

后端 未结 9 601

I\'d like to rebase to a specific commit, not to a HEAD of the other branch:

A --- B --- C          master
 \\
  \\-- D                topic
<
相关标签:
9条回答
  • 2020-12-07 08:40

    There is another way of doing it or if you wish to move back to more than just one commit.

    Here is a an example to move back to n number of commits:

    git branch topic master~n
    

    For the sake of this question, this can also be done:

    git branch topic master~1
    

    The command works perfectly on git version 2.7.4. Haven't tested it on any other version.

    0 讨论(0)
  • 2020-12-07 08:43

    Topic Solution

    The correct command to answer the posted question could be any of the following (assuming branch topic is already checked out):

    git rebase --onto B master
    git rebase --onto master~1 master
    git rebase --onto B A
    git rebase --onto B C
    git rebase --onto B
    

    If topic is not checked out, you simply append topic to the command (except the last one) like so:

    git rebase --onto B master topic
    

    Alternatively, check out the branch first with:

    git checkout topic
    

    Rebase Any String of Commits to a Target Commit

    The basic form of the command we need, cribbed from the documentation, is:

    git rebase --onto <Target> [<Upstream> [<Branch>]]
    

    <Branch> is optional and all it does is checks out the branch specified before executing the rest of the command. If you've already checked out the branch you want to rebase, then you don't need this. Note that you must have specified <Upstream> in order to specify <Branch> or git will think you are specifying <Upstream>.

    <Target> is the commit we will attach our string of commits to. When providing a branch name, you are simply specifying the head commit of that branch. <Target> can be any commit that won't be contained in the string of commits being moved. For example:

    A --- B --- C --- D         master
          \
           \-- X --- Y --- Z    feature
    

    To move the entire feature branch, you can not select X, Y, Z, or feature as the <Target> since those all are commits inside the group being moved.

    <Upstream> is special because it can mean two different things. If it is a commit that is an ancestor of the checked out branch, then it serves as the cut point. In the example I provided, this would be anything that isn't C, D, or master. All commits after <Upstream> until the head of the checked out branch are the ones that will be moved.

    However, if <Upstream> is not an ancestor, then git backs up the chain from the specified commit until if finds a common ancestor with the checked out branch (and aborts if it can't find one). In our case, an <Upstream> of B, C, D, or master will all result in commit B serving as the cut point. <Upstream> is itself an optional command and if it is not specified, then git looks at the parent of the checked out branch which is the equivalent of entering master.

    Now that git has selected the commits it will cut and move, it applies them in order to <Target>, skipping any that are already applied to target.

    Interesting Examples and Results

    Using this starting point:

    A --- B --- C --- D --- E         master
                \
                 \-- X --- Y --- Z    feature
    
    • git rebase --onto D A feature
      Will apply commits B, C, X, Y, Z to commit D and end up skipping B and C because they already have been applied.

    • git rebase --onto C X feature
      Will apply commits Y and Z to commit C, effectively deleting commit X

    0 讨论(0)
  • 2020-12-07 08:46

    A simpler solution is git rebase <SHA1 of B> topic. This works irrespective of where your HEAD is.

    We can confirm this behaviour from git rebase doc

    <upstream> Upstream branch to compare against. May be any valid commit, not just an existing branch name. Defaults to the configured upstream for the current branch.


    You might be thinking what will happen if I mention SHA1 of topic too in the above command ?

    git rebase <SHA1 of B> <SHA1 of topic>

    This will also work but rebase then won't make Topic point to new branch so created and HEAD will be in detached state. So from here you have to manually delete old Topic and create a new branch reference on new branch created by rebase.

    0 讨论(0)
提交回复
热议问题