Desk Clarity

Everyday document & browser help

Git divergent branches: compare merge, rebase and fast-forward-only before pulling

By ON Lab · Sources checked November 8, 2026

When two related branches each contain commits absent from the other, a fast-forward cannot reconcile them. A merge can connect their histories with a merge commit; a rebase can replay local work on the fetched branch. Choose according to the intended history and team policy before changing pull configuration merely to remove a diagnostic.

A historical reader saw a divergent-branches hint in Visual Studio with a Bitbucket repository and asked what the suggested choices actually do. We checked the current Git 2.55 pull manual and tested explicit command-line policies with Git 2.54.0 in disposable local repositories. We did not reproduce Visual Studio, Bitbucket or the original branches.

Inspect the relationship and the intended branch

git status --short
git branch --show-current
git log --oneline --graph --all --decorate
git log --left-right --oneline HEAD...origin/main

Use the real fetched comparison branch for your project. A remote-tracking reference describes your most recently fetched information, so fetch from the reviewed intended remote if it needs updating. The triple-dot comparison shows commits reachable from only one side of the relationship. Commit authorship or a memory of not editing files does not by itself establish that two references have the same ancestry.

Check that the working tree is clean before testing an integration. A branch name pointing to the current commit preserves that committed starting point, but does not by itself preserve uncommitted file changes. Keep those responsibilities separate.

What the three policies did in our fixture

We started from a shared base, created one local commit adding local.txt, and added a different remote commit containing remote.txt. Each test used a separate clean clone with the same kind of divergence. The changes did not overlap.

Explicit pull policyObserved integrationCommit-history consequence
--ff-onlyRejected the divergenceHEAD stayed at the original local commit
--no-rebaseCreated a mergeNew commit had both the local and remote commits as parents
--rebaseReplayed the local changeThe new local commit had a new ID and the remote commit as its parent

We inspected parent IDs and the graph, rather than using command success as a proxy for the desired history. Both successful fixtures retained their intended file additions, but their commit structures differed. Rebase did not merely rename the branch: it produced a commit with a different parent and identity in this test.

Fast-forward-only protected the current branch from that integration. It did not mean the whole pull had no effects. Pull fetches before integration, so fetched objects and remote-tracking information can be updated even when the integration step refuses to move HEAD.

Use one explicit choice after reviewing it

git pull --ff-only origin main

Choose this when the intended policy is to accept only a fast-forward and stop on divergence. If it refuses, inspect the graph. Repeating the same command cannot turn two separate lines of commits into a fast-forward relationship.

git pull --no-rebase origin main

This requests merge integration. In our diverged fixture it made a two-parent merge commit. For a different graph, merge behavior can include a fast-forward, so do not generalize the fixture to “every merge-policy pull creates a merge commit.” Review the resulting graph and content.

git pull --rebase origin main

This requests rebase integration. Review whether the commits being replayed are private local work or shared history that others rely on. Our test had one unshared local commit and no conflicts. A real rebase can need resolutions, drop an already represented change or interact with more complex history.

These commands are alternatives for a reviewed situation, not a sequence to run one after another. Use the branch names appropriate to your repository and inspect the actual result before proceeding.

Separate a one-time choice from a default

A command-line flag makes the intended policy visible for that invocation. A repository pull setting affects later operations in that repository; a global setting affects other repositories as well. Changing every project to one policy is a broader decision than resolving today's branch relationship.

The current Git 2.55 manual describes fast-forward-only as the default when no reconciliation method is supplied. The historical reader's diagnostic and other versions or existing configuration can differ. Our fixture used explicit options, so it does not establish every version's unconfigured default or an IDE's effective settings.

If the project wants a lasting default, record the agreed policy and its scope after the graph and collaboration requirements are understood. Do not assume that a hint listing several commands endorses all of them equally for the current team.

Handle conflicts as a separate review

A merge or rebase can conflict when edits overlap. Inspect the affected content against the intended result before continuing. Git documents merge --abort and rebase --abort for abandoning their corresponding active operations. Match the abort command to the operation actually in progress and preserve unrelated work before starting.

A clean result also needs project checks. A graph can be structurally correct while a build or feature is broken. Read the integrated patch, run relevant checks and confirm the intended files before publishing the branch.

If the histories do not share a root

This fixture's branches had a common ancestor. Separately initialized repositories with independent root commits are another problem. The initial README and unrelated-history guide explains that starting-workflow choice. Do not treat the unrelated-history override as an ordinary divergent-branch policy.

  1. Confirm the current branch, intended fetched branch and working-tree state.
  2. Inspect which commits are exclusive to each side.
  3. Choose a policy consistent with the required collaboration history.
  4. Verify the resulting parents, content and relevant project checks.
  5. Review any lasting configuration separately from the single integration.

Checked November 8, 2026. Git 2.54.0 fixtures verified explicit fast-forward-only, merge and rebase behavior against a shared base. Current upstream documentation was 2.55. No IDE, hosting authentication, push, conflict, dirty-tree or rewritten-upstream case was tested.

Sources