SovranCode
HomeCourses Git & GitHub Git Rebase
This device
Course contentsGit Rebase · 41 topics

1. Git Fundamentals

Git IntroductionGit Version ControlGit vs GitHubGit InstallationGit Working TreeGit RepositoryGit CommitGit .gitignoreGit Project: Learning Journal

2. Git History

Git LogGit DiffGit ResetGit RevertGit StashGit Project: Messy Repository

3. Branches & History

Git BranchGit MergeGit Merge ConflictsGit RebaseGit Cherry-PickGit TagsGit Project: Feature Branch

4. Remotes and GitHub

Git RemoteGitHub AuthenticationGitHub RepositoryGitHub ForkGitHub IssuesGitHub PagesGit Project: Two Clone Sync

5. GitHub Collaboration

GitHub Pull RequestsGitHub Code ReviewGit Branching WorkflowGitHub Branch ProtectionGitHub CollaborationGitHub ContributingGit Project: Reviewed Pull Request

6. Automation and Professional Git

GitHub ActionsGit InternalsGit RecoveryGitHub SecurityGit Project: Team Repository CIProject
Learn Git & GitHub40 complete · 1 planned

1. Git Fundamentals

Git IntroductionGit Version ControlGit vs GitHubGit InstallationGit Working TreeGit RepositoryGit CommitGit .gitignoreGit Project: Learning Journal

2. Git History

Git LogGit DiffGit ResetGit RevertGit StashGit Project: Messy Repository

3. Branches & History

Git BranchGit MergeGit Merge ConflictsGit RebaseGit Cherry-PickGit TagsGit Project: Feature Branch

4. Remotes and GitHub

Git RemoteGitHub AuthenticationGitHub RepositoryGitHub ForkGitHub IssuesGitHub PagesGit Project: Two Clone Sync

5. GitHub Collaboration

GitHub Pull RequestsGitHub Code ReviewGit Branching WorkflowGitHub Branch ProtectionGitHub CollaborationGitHub ContributingGit Project: Reviewed Pull Request

6. Automation and Professional Git

GitHub ActionsGit InternalsGit RecoveryGitHub SecurityGit Project: Team Repository CIProject
PREVIOUS LESSONGit Merge Conflicts
NEXT LESSONGit Cherry-Pick
3. Branches & History 90 min

Git Rebase

Replay commits onto a new base, edit a local series, and refuse rebase on published history that other people already use.

What you will leave with

You will be able to replay a private branch onto a new base, resolve one replayed commit at a time, reorder or combine local commits interactively, compare old and new series, recover the original tip, and explain when merge is the safer integration choice.

Rebase is a controlled history rewrite

ReplayMove a private series to a new parent while preserving intended changes.
EditReword, reorder, squash, split, or drop unpublished commits deliberately.
ProveCompare the old and new series, final trees, tests, and branch graph.
RefuseDo not rewrite shared commits merely to create a prettier graph.

What rebase actually changes

Suppose feature/search contains commits C and D based on A while main has advanced through B. Rebasing finds the branch-specific changes, resets the feature context to B, and replays those changes as C′ and D′.

BEFORE

A—B main

A—C—D feature/search. The histories diverge at A.

AFTER

A—B—C′—D′ feature/search

C′ and D′ express similar patches but have new parents, timestamps, and object IDs.

Same intent does not mean same commits

A commit ID covers its tree, parent, author/committer data, and message. Changing parentage creates new objects. The old C and D remain only while a ref or reflog entry can reach them.

Choose rebase or merge by ownership and evidence

Rebase private work

You alone use the unpublished branch and want to update its base or prepare a coherent review series.

Merge shared work

The commits are already integrated, reviewed by hash, or used as a base by teammates or automation.

Keep meaningful topology

A merge commit can preserve when parallel work converged and which exact histories were integrated.

Follow repository policy

Some teams require merge commits, squash merges, or rebased pull requests. Tool capability does not override that contract.

“Linear history is cleaner” is not enough by itself. A graph is useful when it accurately represents collaboration and supports debugging.

Run a rewrite preflight

git status
git branch --show-current
git fetch origin
git log --oneline --decorate --graph --all
git log origin/main..feature/search --oneline
git log feature/search..origin/main --oneline
git diff origin/main...feature/search
git branch --contains feature/search
  1. 01
    Require a clean state

    Commit, stash, or move unrelated work before changing commit ancestry.

  2. 02
    Confirm ownership

    Know whether anyone fetched, reviewed by hash, or based work on these commits.

  3. 03
    Update remote knowledge

    Fetch before choosing the new base or making publication decisions.

  4. 04
    Record the old tip

    Create a named backup ref and save the graph before a substantial rewrite.

Replay a private branch onto current main

git status
git fetch origin
git log --oneline --decorate --graph --all

# While on the private feature branch:
git switch feature/search
git branch backup/feature-search-before-rebase
git rebase origin/main

If every patch applies, the feature ref advances to the final replacement commit. Main does not move. The backup ref preserves the original series for comparison and recovery.

QUICK CHECK

Test what you learned

Type the command that replays the current private feature branch onto origin/main.

Resolve conflicts one replayed commit at a time

Rebase may stop while applying a specific commit. Read git status and the stopped commit, then resolve its intended change in the context of the updated base.

git status
# Resolve the current replayed commit, then:
git add <resolved-paths>
git diff --cached
git diff --cached --check
git rebase --continue

# Or cancel the entire operation:
git rebase --abort

git rebase --continue records the current replacement commit and advances to the next one. You may need to resolve similar areas more than once because each original commit is replayed separately.

Ours and theirs look reversed during rebase

In a typical rebase conflict, “ours” is the updated upstream plus commits already replayed; “theirs” is the feature commit currently being replayed. Inspect commits and requirements instead of selecting a label mechanically.

Understand continue, skip, and abort

git rebase --continue

Use after staging the verified resolution for the current replayed commit.

git rebase --skip

Omits the current commit. Use only when its complete effect is redundant or intentionally unwanted—and prove that claim.

git rebase --abort

Cancels the operation and returns the branch to its pre-rebase tip.

git rebase --quit

Stops rebasing without resetting HEAD and the working state. This advanced escape differs materially from abort.

An empty replay may be valid

If upstream already contains a patch, Git can drop or report an empty commit. Compare intent and final trees before deciding to skip or preserve an intentional empty commit.

Open an interactive plan

git branch backup/feature-search-before-edit
git rebase -i HEAD~4

The todo list is ordered oldest first because Git will replay it from top to bottom. Changing a line changes the operation; changing line order changes commit order.

pick a1b2c3d add search form
reword b2c3d4e validate empty queries
fixup c3d4e5f fix typo
edit d4e5f6a add result caching

pick / reword

Keep a commit as-is, or keep its patch while editing only the message.

edit

Pause after applying the commit so you can amend or split it.

squash / fixup

Combine with the previous todo commit; squash edits combined messages, while fixup normally discards the fixup message.

drop

Remove a commit from the replacement series. Verify its behavior is truly unwanted or represented elsewhere.

exec

Run a command at a chosen point, such as a focused test, and stop if it fails.

reorder

Move lines only when dependencies permit each intermediate commit to remain coherent.

Amend or split a stopped commit

When interactive rebase stops at edit, HEAD is the replacement version of that commit. Amend it, test, and continue.

# Amend content and/or message
git status
git add <paths>
git commit --amend
git rebase --continue

# Or split the stopped commit into smaller commits
git reset HEAD^
git add <first-paths>
git commit -m "Add search result cache"
git add <remaining-paths>
git commit -m "Test cache invalidation"
git rebase --continue

After the mixed reset, the old commit’s changes remain in the working tree. Build replacement commits with deliberate staging, tests, and messages. Do not continue with valuable changes left unstaged accidentally.

Use fixup commits without hiding review

git commit --fixup=<target-commit>
git rebase -i --autosquash <base-commit>

Autosquash rearranges marked fixup commits beside their targets in the todo list. Review the generated plan before saving; matching a target does not prove the combined patch is correct.

Move only the intended subseries with --onto

The general form is git rebase --onto <new-base> <old-base> <branch>. Git selects commits reachable from the branch but not from the old base and replays them onto the new base.

# Move feature/ui commits off feature/api and onto main
git branch backup/feature-ui-before-onto feature/ui
git rebase --onto main feature/api feature/ui
Draw the graph first

An incorrect old-base boundary can omit wanted commits or replay too many. Confirm the exact set with git log <old-base>..<branch> before running --onto.

Compare old and new series

git status
git log --oneline --decorate --graph --all
git range-diff origin/main...backup/feature-search-before-rebase \
               origin/main...feature/search
git diff backup/feature-search-before-rebase..feature/search
git diff origin/main...feature/search

# Run relevant tests and whitespace checks
git diff origin/main...feature/search --check

git range-diff compares two commit series and helps identify reordered, modified, added, or dropped patches. A zero tree diff between old and new tips can prove identical final content, but not identical intermediate commits or test behavior.

  1. SERIES
    Expected commit mapping

    Every old patch is accounted for as retained, edited, combined, or intentionally dropped.

  2. TREE
    Expected final content

    Tip-to-tip and base-to-tip diffs show no unexplained change.

  3. BUILD
    Relevant checks pass

    Tests validate both final behavior and important intermediate commits when bisectability matters.

  4. GRAPH
    Correct new base

    The rewritten branch descends from the intended updated main commit.

Recover the original history

If the result is wrong, the named backup is the clearest recovery point. Reflog also records recent ref movement for a bounded local period.

git reflog --date=iso feature/search
git show backup/feature-search-before-rebase

# Preserve a discovered old tip before further work
git branch recovery/feature-search <old-tip>

# In a disposable practice branch, restore exactly:
git reset --hard backup/feature-search-before-rebase
Hard reset overwrites tracked working state

Use it only after proving the destination ref and preserving wanted index and working-tree changes. A safer first move is creating a recovery branch and comparing.

Publish a rewrite only under an explicit agreement

If the branch has never been pushed, a normal push publishes the rewritten series. If a remote branch already contains the old series, replacing it is a coordination event—not routine cleanup.

git fetch origin
git log --oneline --left-right origin/feature/search...feature/search

# Only after confirming ownership and team agreement:
git push --force-with-lease origin feature/search

--force-with-lease checks that the remote ref still matches your expected remote-tracking value. It can prevent overwriting unseen remote work, but it cannot repair downstream clones or substitute for communication.

Never rebase shared main to make it prettier

Use a new commit, revert, or merge according to policy. Once others depend on commit IDs, preserving ancestry is usually more valuable than linear appearance.

Guided practice: update and clean a private branch

  1. 01
    Create divergence

    In a disposable repository, make two main commits and four feature commits with one fixup-worthy change.

  2. 02
    Record evidence

    Capture graph, unique ranges, tests, old tip, and a named backup branch.

  3. 03
    Rebase onto main

    Resolve one intentional conflict, inspect the stopped commit, stage the result, and continue.

  4. 04
    Edit the series

    Reword one message, fixup one correction, and split one mixed commit into coherent tested commits.

  5. 05
    Prove the result

    Use range-diff, graph, tree diffs, tests, and clean status before deleting nothing.

Independent lab: rewrite, abort, recover, and publish safely

  1. Create a disposable bare remote and two clones representing you and a teammate.
  2. Build a five-commit private feature series containing a typo fix, a mixed commit, and two commits that should reverse order.
  3. Rebase onto updated main, deliberately abort the first attempt, prove the original tip returned, then rerun.
  4. Use interactive rebase to reword, reorder, autosquash, and split while preserving a named backup.
  5. Use git range-diff, final tree comparison, tests, and graph evidence to account for every patch.
  6. Publish the branch normally. Then simulate a coordinated rewrite and demonstrate that stale lease information prevents overwriting a teammate’s new remote commit.
  7. Recover the pre-rewrite series under a new branch using the backup or reflog, without deleting the verified rewritten branch.
Definition of done

Every old patch has an explained outcome, the feature descends from the intended base, all checks pass, lease protection is demonstrated without losing teammate work, and both old and new tips remain reachable.

Common rebase mistakes

Rebasing shared commits

Replacement IDs force collaborators to reconcile history they already consumed.

Running pull --rebase blindly

Know which local commits will replay onto which fetched upstream before accepting automation.

Skipping a conflict reflexively

Skip discards the current replayed patch. Prove redundancy before using it.

Trusting ours/theirs labels

Rebase side roles differ from normal merge intuition. Inspect stages and commits.

Force pushing without fetching

Stale remote knowledge weakens the lease and risks replacing someone else’s work.

Verifying only final files

A plausible tip can hide a dropped patch, broken intermediate commit, or misleading history.

Lesson review

Rebase is valuable when commit ownership is private and the rewrite has a clear purpose. You can now replay and edit a series while preserving recovery points, resolving operation-specific conflicts, comparing patch series, and refusing rewrites that would destabilize shared history.

  • I explain why rebased commits receive new IDs.
  • I inspect ownership, cleanliness, remote state, and the exact commit range before rewriting.
  • I use interactive commands with oldest-first replay semantics.
  • I verify rewritten series with range-diff, tree diffs, tests, and graph evidence.
  • I use recovery refs and reserve force-with-lease for explicitly coordinated branch replacement.

Related lessons

  • Git Merge Conflicts — Rebase conflicts are resolved per replayed commit.
  • Git Cherry-Pick — Cherry-pick transfers one change without rewriting the branch.
KNOWLEDGE CHECK

Check your rebase safety model

Decide when to replay, edit, verify, recover, publish, or preserve existing ancestry.

01What does rebase do to a feature branch's commits?
02Which branch is the safest routine candidate for rebase?
03During a rebase conflict, what generally does 'ours' refer to?
04What does 'reword' do in an interactive rebase todo list?
05Why should you create a backup ref before a substantial local rewrite?
06If a replayed commit is already present upstream, what might Git do?
07If a coordinated rewritten branch must replace its remote version, which push is the safer guard?
PREVIOUS LESSONGit Merge Conflicts
NEXT LESSONGit Cherry-Pick
ON THIS PAGEGit RebaseRebase is a controlled history rewriteWhat rebase actually changesChoose rebase or merge by ownership and evidenceRun a rewrite preflightReplay a private branch onto current mainResolve conflicts one replayed commit at a timeUnderstand continue, skip, and abortOpen an interactive planAmend or split a stopped commitUse fixup commits without hiding reviewMove only the intended subseries with --ontoCompare old and new seriesRecover the original historyPublish a rewrite only under an explicit agreementGuided practice: update and clean a private branchIndependent lab: rewrite, abort, recover, and publish safelyCommon rebase mistakesLesson reviewKnowledge checkRelated lessons
Course contents