Skip to content

Instantly share code, notes, and snippets.

@bewuethr
Last active July 3, 2023 18:55
Show Gist options
  • Save bewuethr/03c0c83dc55e325ee5bcf5dd980b0d2f to your computer and use it in GitHub Desktop.
Save bewuethr/03c0c83dc55e325ee5bcf5dd980b0d2f to your computer and use it in GitHub Desktop.
Partially rebasing a branch

Rebasing branches partially in Git

Situation

Feature branch feature1 is cut from development:

---o---o---o      <-- development
    \
     A---B---C    <-- feature1

A second branch, feature2, is cut from feature1:

---o---o---o                <-- development
    \
     A---B---C              <-- feature1
              \
               1---2---3    <-- feature2

Now, feature1 is squash merged into development, so x contains the changes in A, B, and C.

---o---o---o---x            <-- development
    \
     A---B---C              <-- feature1
              \
               1---2---3    <-- feature2

Or, if head branches are automatically deleted, feature2 gets rebased onto development:

---o---o---o---x             <-- development
    \
     A---B---C---1---2---3   <-- feature2

Problem

How can I merge feature2 into development without merge conflicts?

Solutions

Cherry-picking

Cut a new branch from development and cherry-pick the changes in feature2;

git checkout development
git checkout -b feature2-new
git cherry-pick 1 2 3

This results in

---o---o---o---x                <-- development
   |            \
   |             1'---2'---3'   <-- feature2-new
    \
     A---B---C                  <-- feature1
              \
               1---2---3        <-- feature2

Then, rename the new branch, overwrite the old name; -M is --move --force:

git branch -M feature2

resulting in

---o---o---o---x                <-- development
   |            \
   |             1'---2'---3'   <-- feature2
    \
     A---B---C                  <-- feature1
              \
               1---2---3        <-- (feature2, deleted)

Rebase with --onto

More elegant: git rebase has an --onto option, so we can use the command in the form

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

where

  • <newbase> is where the new commits will be created (development)
  • <upstream> is the last commit we don't want to move (feature1)
  • <branch> is the branch we want to rebase (feature2)

so

git rebase --onto development feature1 feature2

results in

---o---o---o---x                <-- development
   |            \
   |             1'---2'---3'   <-- feature2
    \
     A---B---C                  <-- feature1

If feature1 doesn't exist any longer, we have to use the commit directly:

git rebase --onto development C feature2
@thepuzzlemaster
Copy link

Thanks! This is a super clear explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment