git rebase
The official Git manpage on man7.org defines the core function as: "Reapply commits on top of another base tip". Git takes the commits from a branch and replays them, but now on top of another commit — usually the current HEAD of the main branch. The result is that the commits from the feature branch appear as if they were created only after the latest changes from the main branch had been added. The final code is identical to a merge, but the history looks different: linear instead of branched.
Steps
1. Fetch the latest changes
Before you rebase, you must fetch the latest remote changes. Use `git fetch` to update the remote-tracking branches without affecting your local work.git fetch origin
This fetches all new commits from the remote but changes nothing about your local branches. You can now see where `origin/main` stands relative to your local branch.
2. Switch to your feature branch
Make sure you are on the branch you want to rebase. If you are still on another branch, switch first.git checkout feature-branch
Replace `feature-branch` with the name of your branch. Check with `git branch` that you are on the correct branch before continuing.
3. Rebase onto the main branch
Perform the rebase with `origin/main` as the new base. This reapplies all your local commits on top of the latest commits from the main branch.git rebase origin/main
Git now takes each commit from your feature branch and reapplies it, one by one, on top of `origin/main`. If conflicts occur, Git stops and lets you resolve them.
4. Resolve conflicts
If Git reports conflicts, open the conflicting files. Git marks the conflicts with `<<<<<<<`, `=======`, and `>>>>>>>`. Resolve each conflict manually and save the file.git add conflicterend-bestand.txt
git rebase --continueGit continues with the next commit. Repeat this until all commits have been applied. If you want to stop, use `git rebase --abort` to return to the situation before the rebase.
5. Interactive rebase for history editing
Use `git rebase -i` to actively edit history. This opens an editor with a list of commits. The command `git rebase -i HEAD~3` shows the last three commits.git rebase -i HEAD~3
In the editor, you will see lines like `pick a1b2c3d Commit-bericht`. You can replace `pick` with one of these options:
- `reword` — change only the commit message
- `edit` — change the content of the commit
- `squash` — merge the commit with the previous one
- `fixup` — merge without keeping the message
- `drop` — remove the commit
6. Push after rebase
If the branch was already pushed earlier, you must perform a force push. This is necessary because the commit IDs have changed due to the rebase.git push --force-with-lease origin feature-branch
`--force-with-lease` is safer than `--force`: it refuses the push if someone else has pushed new commits to the branch in the meantime.
7. Rebase with git-rerere
For workflows with frequent rebases, you can enable `git-rerere`. This tool automatically reuses resolved merge conflicts.git config --global rerere.enabled true
When you resolve a conflict, Git records the resolution. At the next conflict that resembles it, Git automatically applies the recorded resolution.
8. Check the result with git-range-diff
`git-range-diff` compares two commit ranges — for example, before and after a rebase. This shows what exactly changed in the history.git range-diff origin/main...main feature-branch...feature-branch
This command compares the commit ranges and shows, per commit, which changes were made. This is useful when multiple commits have been rewritten or squashed.
Verification
Check whether the rebase succeeded with:git log --oneline --graph --decorate
This shows the commit history. You will see a linear line without branches. The commits from your feature branch sit on top of the latest commits from `origin/main`. No merge commit is visible.
Also check that the code works correctly:
git status
This should show "nothing to commit, working tree clean" if all conflicts have been resolved and the rebase is complete.
Common problems
1. "Cannot rebase: You have unstaged changes"
Git refuses to rebase with uncommitted changes. Resolve this by stashing your changes:git stash
git rebase origin/main
git stash popThe stash is reapplied after the rebase.
2. Conflict keeps coming back with every commit
When the same conflict occurs with every commit, use `git-rerere`. Enable it before starting the rebase:git config --global rerere.enabled true
Git records your resolution the first time and automatically applies it afterwards.
3. "Updates were rejected" when pushing
This means the remote branch differs from your local branch after the rebase. Use `--force-with-lease`:git push --force-with-lease origin feature-branch
This overwrites the remote branch, but refuses if others have pushed new commits.
Why rebasing is dangerous
`git rebase` rewrites history and thereby changes the commit IDs. If a branch has already been shared with others, they will see a mismatch between their local history and the shared version. The guideline is therefore: rebasing commits that have not yet been pushed or shared is safe; rebasing shared history is discouraged. `git reset` and `git restore` also play a role in history management, but do not replace `rebase`. `git reset` moves HEAD to an earlier commit — destructive. `git restore` restores files in the working directory or index, useful after a mistake in an interactive rebase.The term "rebase" has been in use since the early days of Git. A howto document on kernel.org dated August 14, 2005 describes the concept of "forward port these changes" — moving changes from a fork-point to the main branch. That was a manual procedure at the time; it was soon automated in the `git rebase` command. The technical specification is in the manpage `git-rebase(1)`, maintained by Junio C. Hamano and Johannes E. Schindelin, whose names and email addresses appear on the manpage as published on Linux die.net. The current manpage on man7.org confirms the same core definition: "Reapply commits on top of another base tip".
Beyond core Git, there are tools that support rebase workflows. Gitpulsar, a native Git client for GNOME written in Rust, offers a fast, offline-working interface without telemetry. Commit is an editor that helps write better commit messages. These tools do not replace `git rebase`, but support workflows in which the command is used regularly.
The core question remains: do you want a history that accurately reflects what happened, or a history that reflects what should have happened?