Timur Fayzrakhmanov
Timur Fayzrakhmanov

Reputation: 19587

Git rebase arguments context explanation needed

Very often git rebase used in a context of some branch. For example, if I want to move the base of feature branch on top of the master branch (based on latest commits) - tutorials say:

git checkout feature
git rebase master 

After tutorials like that, there are a lot of questions. Eg: how to perform the same action without checking out. How can I do the same action with --onto option. What the difference between --onto and just rebase. Can I pass a range of commits or it must be a whole branch? Etc..

I've read man page several times but still have a big gap.

So the main problem is: how git parse the args in different scenarios and how should I interpret/imagine them in my head? For example:

git rebase master
git rebase feature master
git rebase --onto master feature
git rebase HEAD~4 HEAD~2
git rebase --onto HEAD~4 HEAD~2

Let's assume we have the following repo:

Z -- W (HEAD, test-branch*) 

A -- B -- C -- D -- E (master)
     \
      1 -- 2 -- 3 (feature)

test-branch is checked out.

Upvotes: 10

Views: 2140

Answers (2)

Schwern
Schwern

Reputation: 164919

The full rebase command is this.

git rebase --onto <onto> <upstream> <branch-to-rebase>

Git will take all the changes in branch-to-rebase which are not in upstream and put them on top of onto.

The defaults are...

  • branch-to-rebase: current branch
  • upstream: branch-to-rebase's tracking branch
  • onto: upstream

git checkout feature; git rebase master is really git rebase --onto master master feature.

You generally want onto and upstream to be the same, but sometimes it's useful for them to be different for delicate surgery. The difference between upstream and onto is made clear in this example.

           A--B--C--D master
               \
                E--F--G next
                       \
                        H--I--J topic

If you git rebase master topic, it will rebase all the commits that topic does not have in common with master. All intervening branch heads will be ignored. That is E, F, G, H, I and J. Since onto defaults to upstream, it will put those on master. You'll wind up with this.

           A--B--C--D master
               \     \
                \     E'-F'-G'-H'-I'-J' topic
                 \
                  E--F--G next

What if you just want the commits from next to topic? This is where --onto becomes useful. Tell Git that the upstream is next, but you want to rebase onto master. So run git rebase --onto master next topic. This will select just H, I and J.

           A--B--C--D master
               \     \
                \     H'-I'-J' topic
                 \
                  E--F--G next

Upvotes: 16

VonC
VonC

Reputation: 1325137

git rebase man page.

  • git rebase master rebases the current branch on top of master (meaning master is checked out, and the current branch is reset to master, its commits are rebased on top of it).

Considering the current branch is test-branch:

A -- B -- C -- D -- E -- Z' -- W' (test-branch)
                 (master)
  • git rebase feature master replays master commits on top of feature (rare, the best practice is to do the opposite)

That is:

A -- B
      \
       1 -- 2 -- 3 -- C' -- D' -- E' (master)
              (feature)
  • git rebase --onto master feature would move all commits after feature up to the current branch on top of the new base master.
    Since feature and test-branch are not related, that wouldn't move any commit.

  • git rebase HEAD~4 HEAD~2 reset the current branch to @~2

For a test-branch like Z -- Y -- X -- W, that would mean Z -- Y

  • git rebase --onto HEAD~4 HEAD~2 would remove @~3 and @~2 from the current branch since it replay all commit from after @~2 (that is @~1 and @) onto the new base @~4.

Upvotes: 2

Related Questions