# Rebase

### Rationale

* Change the base of a branch;
* After rebasing, there are still two branches, similar to a fast-forward merge situation;
* Rebasing is creating new commits, hence the SHA will be different even though it's the same change set;

### Notes

* Rebase re-assigns the common ancestor of a branch to a different commit, i.e. changing the base of a branch.
* By default, a rebase will drop merge commits, and place the rebased commits into a single, linear branch. To try include merged commits, use the `--rebase-merges` option.
* It's similar to merge, but
  * meerge maintains the branching history;
  * rebase puts one branch at the end of another.
* Rebase is suitable if you want to maintain a single-branch paradigm.
* It will interfere with the commit history, so only apply it locally with caution.

### Command

#### Use the current branch as base

* Checkout the branch to be rebased
* `git rebase <new-base>`

#### Use any two branches

* `git rebase <b1> <b2>` will rebase `b2` on `b1` (equiv. to checkout `b2`, then rebase on `b1`)

#### Check divergence

* `git merge-base <b1> <b2>` returns commit where `b2` diverges from `b1`

#### Onto other branches

* `git rebase --onto master ecommerce new_feature` will gather the commits from `new_feature` diverged from `ecommerce` and put them onto `master`.

#### Undo

* `git reset --hard ORIG_HEAD`
  * `ORIG_HEAD` is the previous state of `HEAD` so that dangerous operations can be reverted.
  * This assumes no other destructive operations are done after the rebase.
* Alternatively, rebase again to restore the original structure, but the SHA value will be changed.

### Conflicts

If conflicts occur

* Modified the files to the final state you want. Then add the files to the staging tree (`git add`). Instead of commit, use `git rebase --continue` to finish rebasing.
* You might need to do this multiple times if more than one conflict is found.

#### Manually resolve the conflict

* `git add <file>`, then
  * `git rebase --continue` to continue
  * No commit required as the commit history is in the branch
* `git rebase --abort` to cancel
* `git rebase --skip` to skip the conflict
