Update code with fetch, merge, and pull

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Visual Studio 2019 | Visual Studio 2022

When there are several contributors to a project, keep your local Git repo updated by downloading and integrating work that others uploaded to the project's remote repo. These Git commands update your local repo:

  • Git fetch downloads any new commits that others uploaded to the remote repo. The remote-tracking branches in local repo cache are updated—local branches remain unchanged.
  • Git merge integrates commits from one or more source branches into a target branch.
  • Git rebase integrates commits from a source branch into a target branch, but uses a different strategy than Git merge.
  • Git pull performs a fetch and then a merge or rebase to integrate fetched commits into your current local branch.

Visual Studio uses a subset of those Git commands when you synchronize your local repo with a remote repo.

For an overview of the Git workflow, see Azure Repos Git tutorial.

This article provides procedures for the following tasks:

  • Download changes with fetch
  • Update branches with merge or rebase
  • Download changes and update branches with pull

Download changes with fetch

Git fetch downloads remote branch commits and referenced file objects that don't exist in your local repo and updates the remote-tracking branches in local repo cache. Remote-tracking branches are locally cached read-only copies of remote branches and aren't your local branches. Git fetch doesn't update your local branches. For example, if a remote repo designated by origin has a bugfix3 branch, Git fetch will update the remote-tracking branch named origin/bugfix3 and not your local bugfix3 branch. You can use remote-tracking branches to:

  • Compare a remote-tracking branch with a local branch to review fetched changes.
  • Merge a remote-tracking branch into a local branch.
  • Create a new local branch from a remote-tracking branch.

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.

  1. In the Git Changes window, choose Fetch. Then select outgoing/incoming to open the Git Repository window.

    Screenshot of the Fetch buttons and Incoming link in the Git Changes window of Visual Studio 2019.

    You can also choose Fetch from the Git menu.

    Screenshot of the Fetch option in the Git menu in Visual Studio 2019.

  2. In the Git Repository window, fetched commits appear in the Incoming section. Select a fetched commit to see the list of changed files in that commit. Select a changed file to see a diff view of changed content.

    Screenshot of the Git Repository menu in Visual Studio 2019.

Tip

Fetch won't delete remote-tracking branches in your local repo cache that no longer have a remote counterpart. To configure Visual Studio to prune stale remote-tracking branches during a Fetch:

  • Select Tools > Options > Source Control > Git Global Settings.
  • Set the Prune remote branches during fetch option to True.

After a Git fetch, you can compare a local branch with its corresponding remote-tracking branch to see what changed on the remote branch. If you decide to update your current local branch with fetched changes, you can perform a Git merge or rebase. Or, you can run Git pull, which combines a Git fetch with a Git merge or rebase. Both Git merge and Git rebase update a target branch by applying commits from a source branch onto it. However, Git merge and Git rebase use different strategies. For more information, see Update branches with merge or rebase and When to rebase vs. merge.

Update branches with merge or rebase

Git merge and Git rebase integrate commits from a source branch into your current local branch (target branch). Git merge performs either a fast-forward or a no-fast-forward merge. The no-fast-forward merge is also known as a three-way merge or true merge. Git rebase is another type of merge. These merge types are shown in the following diagram.

Diagram showing the before and after commits when using merge and rebase.

Git merge and Git rebase are extensively used in the Git workflow. When working on a local feature or bugfix branch, it's common practice to:

  1. Keep your local main branch current with its remote counterpart by periodically pulling to fetch and merge remote commits.
  2. Integrate local main branch updates into your local feature branch using a rebase or merge.
  3. Back up your work on the local feature branch by pushing it to the corresponding remote branch.
  4. On feature completion, create a pull request to merge your remote feature branch into the remote main branch.

This approach helps you:

  • Stay aware of recent work by others that might affect your work.
  • Promptly resolve any conflicts between your work and that of others.
  • Apply your new feature on top of up-to-date project content.
  • Get a pull request review of your work.

Merge

For Git merge, if the tip of the target branch exists within the source branch, the default merge type will be a fast-forward merge. Otherwise, the default merge type will be a no-fast-forward merge.

A fast-forward Git merge can never have a merge conflict because Git won't apply a fast-forward merge if the tip of the target branch has diverged from the source branch. By default, Git uses a fast-forward merge whenever possible. For example, Git will apply a fast-forward merge on a local branch that you only update by pulling from its remote counterpart branch.

A no-fast-forward Git merge generates a new target branch "merge commit" that integrates source branch changes with target branch changes. The applicable changes are those made after the last commit that's common to both branches. In the preceding diagram, commit C is the last common commit in both branches. If any source branch change conflicts with any target branch change, then Git will prompt you to resolve the merge conflict. The merge commit (L) contains the integrated source branch and target branch changes. The source and target branch tips (K and E) are the parents of the merge commit. In your branch's commit history, a merge commit is a useful marker for a merge operation, and clearly shows which branches were merged.

Git merge only modifies the target branch—the source branch remains unchanged. When you encounter one or more merge conflicts, you must resolve them to complete the merge. Or, you can cancel the merge operation and return the target branch to its prior state.

For more information on merge options and strategies, see the Git reference manual and Git merge strategies.

Tip

If the source branch is a remote-tracking branch, ensure that branch is up-to-date by running a Git fetch before the merge.

  1. Choose Git > Manage Branches from the menu bar to open the Git Repository window.

    Screenshot of the Manage Branches option in the Git menu of Visual Studio 2019.

  2. In the Git Repository window, right-click the target branch and select Checkout.

    Screenshot of the Checkout option in the Git Repository window of Visual Studio 2019.

  3. Right-click the source branch, and select Merge <source-branch> into <target-branch>.

    Screenshot of the Merge option in the Git Repository window of Visual Studio 2019.

  4. Visual Studio will display a confirmation message after a successful merge.

    Screenshot of the merge confirmation message in the Git Repository window of Visual Studio 2019.

    If the merge is halted due to merge conflicts, Visual Studio will notify you. You can either resolve the conflicts, or cancel the merge and return to the pre-merge state.

    Screenshot of the merge conflict message in the Git Repository window of Visual Studio 2019.

Rebase

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 Git rebase replays the changes in your target branch on top of the source branch history. If any source branch change conflicts with any target branch change, then Git will prompt you to resolve the merge conflict. Git rebase doesn't create a merge commit. 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.

Git rebase only modifies the target branch—the source branch remains unchanged. When you encounter one or more merge conflicts, you must resolve them to complete the rebase. Or, you can cancel the rebase operation and return the target branch to its prior state.

If you're the only person working on your feature or bugfix branch, consider using Git rebase to integrate new main branch commits into it. Otherwise, use Git merge. For more information on Git rebase and when to use it, see Apply changes with rebase and Rebase vs merge.

Tip

If the source branch is a remote-tracking branch, ensure that branch is up-to-date by running a Git fetch before the rebase.

  1. Choose Git > Manage Branches to open the Git Repository window.

    Screenshot of the Manage Branches option in the Git menu of Visual Studio 2019.

  2. In the Git Repository window, right-click the target branch and select Checkout.

    Screenshot of the Checkout option in the branch context menu in the Git Repository window of Visual Studio 2019.

  3. Right-click the source branch, and select Rebase <target-branch> onto <source-branch>.

    Screenshot of the Rebase option in the branch context menu in the Git Repository window of Visual Studio 2019.

  4. Visual Studio will display a confirmation message after a successful rebase.

    Screenshot of the rebase confirmation message in the Git Repository window of Visual Studio 2019.

    If the rebase is halted due to merge conflicts, Visual Studio will notify you. You can either resolve the conflicts, or cancel the rebase and return to the pre-rebase state.

    Screenshot of the rebase conflict message in the Git Repository window of Visual Studio 2019.

Download changes and update branches with pull

By default, Git pull combines a Git fetch and a Git merge to update your current local branch from its remote counterpart. Optionally, Git pull can perform a Git rebase instead of a Git merge.

Unlike Git fetch, Git pull will update your current local branch immediately after downloading new commits from the remote repo. Use Git pull when you know you want to update your current local branch right after a Git fetch.

Tip

To configure Visual Studio to rebase instead of merge when you Pull:

  1. From the Git menu, go to Tools > Options > Source Control > Git Global Settings.
  2. Set the Rebase local branch when pulling option to True.
  1. In the Git Changes window, choose Pull.

    Screenshot of the Pull button in the Git Changes window of Visual Studio 2019.

    You can also choose Pull from the Git menu.

    Screenshot of the Pull option in the Git menu in Visual Studio 2019.

  2. A confirmation message displays when the pull operation completes.

    Screenshot of the pull confirmation message in the Git Changes window in Visual Studio 2019.

    If there are conflicts during the merge portion of the pull operation, Visual Studio will notify you. You can either resolve the conflicts, or cancel the merge and return to the pre-merge state.

    Screenshot of the pull conflict message in the Git Changes window in Visual Studio 2019.

Note

In Visual Studio, Sync performs a Pull then a Push to synchronize a local and remote branch. For more information on Sync, see Use git fetch, pull, push and sync for version control in Visual Studio.

Next steps