This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Download Microsoft Edge
More info about Internet Explorer and Microsoft Edge
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019 | TFS 2018
Visual Studio 2019 | Visual Studio 2022
Git automatically maintains a
history
of development on a
branch
by linking each new
commit
to its predecessor. When you
merge
one branch into another, the history can become less straightforward. For example, a
no-fast-forward merge
combines divergent lines of development by creating a merge commit with multiple predecessors. Conversely, a Git
rebase
combines divergent lines of development without creating a merge commit, which results in a simpler commit history but loses information about the merge. Your choice of
merge type
is likely influenced by whether you want to preserve a record of the merge or simplify the commit history.
This article discusses when to use a rebase instead of a no-fast-forward merge, and provides procedures for the following tasks:
Rebase your local branch
Force push your local branch after a rebase
Interactive rebase to squash local commits
For an overview of the Git workflow, see
Azure Repos Git tutorial
.
Rebase your local branch
Git
rebase
integrates commits from a source branch into your current local branch (target branch). The source branch remains unchanged. For comparison, Git rebase and other merge types are shown in the following diagram.
Git rebase resequences the commit history of the target branch so that it contains all source branch commits, followed by all target branch commits since the last common commit. Another way to view it is that a rebase replays the changes in your target branch on top of the source branch history. Notably, Git rebase changes the sequence of the existing target branch commits, which isn't the case for the other merge strategies. In the preceding diagram, commit K' contains the same changes as K, but has a new commit ID because it links back to commit E instead of C.
During a rebase, if a source branch change conflicts with a target branch change, Git will prompt you to
resolve the merge conflict
. You can resolve merge conflicts during a rebase in the same way that you resolve merge conflicts during a merge.
Rebase vs. no-fast-forward merge
Git rebasing results in a simpler but less exact commit history than a
no-fast-forward
merge, otherwise known as a
three-way
or
true
merge. When you want a record of a merge in the commit history, use a no-fast-forward merge.
If you're the only person working on a feature or bugfix branch, consider using a rebase to periodically integrate recent
main
branch work into it. That strategy helps ensure that you stay aware of recent work by others and promptly resolve any merge conflicts that arise. By rebasing, you implement your new feature on top of the most recent
main
branch work, which helps maintain a linear commit history.
For more information on Git rebase and when to use it, see
Rebase vs merge
.
Rebase and force-push guidelines
If you rebase a local branch that you've previously
pushed
, and then run the default Git push command again, the push will fail. The default Git push command applies a fast-forward merge to integrate your local branch into the remote branch. That command will fail after a rebase because the rebase alters the sequence of existing commits in your local target branch, so it no longer matches the history of its remote counterpart. In this scenario, a
force push
will succeed—by overwriting the remote branch.
Git rebase and force push are powerful tools, but keep these guidelines in mind when deciding whether to use them:
Don't rebase a local branch that's been pushed and shared with others, unless you're certain no one is using the shared branch. After a rebase, your local branch will no longer match the history of its remote counterpart.
Don't force push to a remote branch that's in use by others, since their local version of the remote branch will no longer match the updated remote branch history.
Your team should agree on the usage scenarios for rebase and force push.
For a collaborative review process, use a
pull request
to merge new work into the default branch of a remote repo.
How to rebase
Visual Studio 2022
Visual Studio 2019 - Git menu
Visual Studio 2019 - Team Explorer
Git Command Line
Visual Studio 2022 provides a Git version control experience by using the
Git
menu,
Git Changes
, and through context menus in
Solution Explorer
. Visual Studio 2019 version 16.8 also offers the
Team Explorer
Git user interface. For more information, see the
Visual Studio 2019 - Team Explorer
tab.
Choose
Git > Manage Branches
to open the
Git Repository
window.
Visual Studio 2019 provides a Git version control experience by using the
Git
menu,
Git Changes
, and through context menus in
Solution Explorer
.
Choose
Git > Manage Branches
to open the
Git Repository
window.
Visual Studio 2019 version 16.8 and later versions provides a Git version control experience while maintaining the
Team Explorer
Git user interface. To use
Team Explorer
, uncheck
Tools
>
Options
>
Preview Features
>
New Git user experience
from the menu bar. You can use Git features from either interface interchangeably.
In
Team Explorer
, select
Home
and choose
Branches
.
To integrate source branch commits into a target branch, run the
git rebase
command:
git rebase <source branch name> <target branch name>
If your current local branch is the target branch, you can simplify the rebase command to:
git rebase <source branch name>
Git will notify you if there are conflicts during the rebase. You can either resolve the conflicts and then run git rebase --continue, or run git rebase --abort to undo the rebase and return to the pre-rebase state.
Force push your local branch after a rebase
If you rebase a local branch that you've previously pushed, a subsequent default Git push will fail. Instead, you can force push your local branch to overwrite its remote counterpart so that their commit histories match.
Warning
Never force push a branch that others are working on. For more information, see Rebase and force push guidelines.
To force push in Visual Studio, you must first enable the force push option:
Go to Tools > Options > Source Control > Git Global Settings.
Select the Enable push --force-with-lease option.
The Git push --force-with-lease flag is safer than the --force flag because it won't overwrite a remote branch that has commits that aren't integrated within the local branch you're force pushing.
Visual Studio 2022
Visual Studio 2019 - Git menu
Visual Studio 2019 - Team Explorer
Git Command Line
Visual Studio 2019 version 16.8 and later versions provides a Git version control experience while maintaining the Team Explorer Git user interface. To use Team Explorer, uncheck Tools > Options > Preview Features > New Git user experience from the menu bar. You can use Git features from either interface interchangeably.
In Team Explorer, select Home and then choose Sync to open the Synchronization view.
The Git push --force-with-lease flag is safer than the --force flag because it won't overwrite a remote branch that has commits that aren't integrated within the local branch you're force pushing.
To force push new commits from your local branch to a same-named remote branch:
git push --force-with-lease <remote> <local branch name>
If the branch you want to push is your checked out branch, you can simplify the force push command to:
git push --force-with-lease <remote>
When you clone a remote repo, Git assigns the alias origin as shorthand for the URL of the remote repo that you cloned. Run git remote -v to check the origin alias value. To add the origin alias manually, run git remote add origin <remote repo url>. With the origin alias, you can further simplify the force push command:
git push --force-with-lease origin
If your current local branch tracks a remote branch on origin, you can fully abbreviate the force push command:
git push --force-with-lease
However, the fully abbreviated push command will fail if your local branch doesn't track a remote branch. Run git remote show origin to check the tracked status of your branches.
Interactive rebase to squash local commits
Typically, as you work on a new feature in your local feature branch, you'll create multiple commits. When you're ready to publish the new feature, you might want to consolidate those commits into a single commit to simplify the commit history. You can use an interactive rebase to squash multiple commits into a single commit.
Visual Studio 2022
Visual Studio 2019 - Git menu
Visual Studio 2019 - Team Explorer
Git Command Line
Check out the local branch that you want to perform an interactive rebase on.
Commit, stash, or discard any uncommitted changes.
Estimate how far back in the commit history you want to go. You don't have to be exact as you'll get to pick out specific commits to squash when you run the interactive rebase command. For example, if you want to squash commits within the last five commits, run:
git rebase -i HEAD~5
Git will open an editor that lists the last five commits, starting with the most recent. For example:
pick 7068b09 Update README network switch section
pick 9d247f7 Update README network controller section
pick 5d7ab9f Fix fiber optic transmitter test
pick 7b43f3f Add network switch test
pick 00859d9 Add network controller test
Leave the first line as is. On subsequent lines, to merge a commit with the one above it, change pick to squash. For example, to combine the top two commits and also the bottom two commits, modify the commit list to:
pick 7068b09 Update README network switch section
squash 9d247f7 Update README network controller section
pick 5d7ab9f Fix fiber optic transmitter test
pick 7b43f3f Add network switch test
squash 00859d9 Add network controller test
Save and close the editor. Git will then open a new editor for each set of merged commits, prompting you to enter a commit message. For each commit set, condense the commit messages down to one message, then save and close the editor. In the preceding example, the squashed commits are condensed with new commit messages:
8fcb88f Update README network sections
ac6d3c0 Fix fiber optic transmitter test
f0aadc3 Add two network tests
Even though the commit Fix fiber optic transmitter test wasn't squashed, it has a new commit ID because it now links to a different predecessor commit.
For more information about interactive rebasing, see Git rebase interactive mode.
Azure DevOps users can squash merge to condense the commit history of a topic branch during a pull request.
Next steps
Copy changes with cherry-pick
Related articles
New to Git repos? Learn more
Share code with push
Update code with fetch, merge, and pull