skip to content

In Git, what does branch.autoSetupMerge control when you create a new branch?

level: middleimportance: nice to knowfreq 28%

answer

  1. It is about branch creation, not pushing
  2. Decides whether upstream config is written
  3. Depends on what you branched from
  4. Default only tracks remote-tracking start points
  5. --track and --no-track override per command

basics

~20 s

branch.autoSetupMerge decides whether a newly created branch automatically gets upstream configuration. At its default value true, Git sets the upstream only when the new branch starts from a remote-tracking branch; false never does, always does it for local start points too.

solid answer

~40 s

When you create a branch, Git may write `branch.<new>.remote` and `branch.<new>.merge` for you. `branch.autoSetupMerge` governs that. The default, `true`, means "set the upstream when the start point is a remote-tracking branch" — which is why `git switch -c feature origin/feature` tracks automatically, and why the DWIM form `git switch feature` creates a tracking branch when exactly one remote has that name. `false` disables it entirely, so new branches never get an upstream. `always` also sets it when branching from a *local* branch, making the new branch track the local one. You can override per command with `--track` or `--no-track` on `git branch`, `git switch -c`, or `git checkout -b`. A sibling setting, `branch.autoSetupRebase`, decides whether `branch.<name>.rebase` is set at the same time.

code

console · 8 lines
console
$ git switch -c feature origin/feature
branch 'feature' set up to track 'origin/feature'.

$ git switch -c spike main
Switched to a new branch 'spike'
$ git config --get branch.spike.merge
$ echo $?
1

go deeper

for a junior

Recall that branching from origin/feature usually sets tracking automatically while branching from a local branch does not, and that --track and --no-track let you choose explicitly.

for a middle

Explain the config key, its default of true, and what each value does — including that always makes a new branch track a local branch rather than a remote one.

for a senior

Connect it to the symptoms you see in a team: branches with no upstream, or branches mysteriously tracking a local branch, and know the DWIM checkout and checkout.defaultRemote behaviour behind ambiguous names.

for a principal

Argue for defaults deliberately: leave autoSetupMerge alone and reach for push.autoSetupRemote if contributors keep hitting no-upstream errors, rather than making branches track local branches team-wide.

## The problem it solves Creating a branch is a local, cheap operation, but a branch is much more useful once Git knows which remote branch it corresponds to: bare `git push` and `git pull` work, `git status` reports ahead/behind, and `@{u}` resolves. `branch.autoSetupMerge` is the policy knob for *when Git guesses that for you* instead of making you pass `-u` or `git branch -u`. ## The values - **`true`** (default) — configure the upstream when the branch's **start point is a remote-tracking branch**. `git switch -c feature origin/feature` therefore sets `branch.feature.remote = origin` and `branch.feature.merge = refs/heads/feature`. Branching from a local branch sets nothing. - **`false`** — never configure an upstream automatically. Every branch starts unlinked, and a bare `git push` on it fails with "The current branch has no upstream branch" until you set one explicitly. - **`always`** — also configure it when the start point is a **local** branch, in which case the new branch tracks that local branch. Ahead/behind then compares against a local ref, which some people like for stacked branches and others find confusing. Newer Git versions accept further values that refine the behaviour; if you are not certain which your installation supports, `git help config` on the running version is the authority. ## The DWIM checkout A closely related convenience: `git switch feature` (or `git checkout feature`) with no local branch of that name will, when exactly **one** remote has `feature`, create a local branch from `origin/feature` and set the upstream. That behaviour is part of the same auto-setup machinery and is disabled by `--no-guess` on `git switch`. When several remotes carry the same branch name the guess is ambiguous and fails; `checkout.defaultRemote` names which remote wins in that situation. ## Per-command overrides Configuration is the default; flags decide individual cases. - `--track` (`-t`) forces upstream configuration even from a local start point. - `--no-track` suppresses it even from a remote-tracking start point. Both work on `git branch`, `git switch -c`, and `git checkout -b`. `--track` also accepts an explicit form on `git branch` where you name the start point, and `git branch -u` / `--set-upstream-to` remains the way to fix things after the fact. ## The rebase sibling `branch.autoSetupRebase` decides whether Git additionally writes `branch.<name>.rebase = true`, which makes `git pull` on that branch rebase instead of merge. Its values select which kinds of start point trigger it: never (the default), only local branches, only remote-tracking branches, or always. Teams that want rebase-by-default usually reach for the global `pull.rebase` instead, since it applies to existing branches too rather than only newly created ones. ## Why an interviewer asks Mostly to see whether you know that automatic tracking is *policy*, not magic — and that you can turn it off. The practical scenarios are two: someone whose branches never track anything (someone set `false`, or they branch from local `main` under the default) and someone surprised that a branch tracks a local branch (`always` is in effect). Being able to name the config key, its default, and the `--track` / `--no-track` escape hatches is the whole answer. ## Practical guidance Leaving the default alone is right for most teams. If contributors keep hitting the no-upstream error, the modern fix is not `always` — which links branches to local ones — but the newer `push.autoSetupRemote` setting, which makes a branch's first bare push create the remote branch and set its upstream in one step.

  • Why does git switch -c feature origin/feature track automatically, while branching from local main does not?
    Because `branch.autoSetupMerge` defaults to `true`, meaning "set the upstream when the start point is a remote-tracking branch". `origin/feature` is one; local `main` is not. Setting the value to `always` would make the local case track too, and `false` disables both. Per command, `--track` and `--no-track` override whichever default is in force.
  • How do you create a branch from origin/main without any upstream configuration?
    Pass `--no-track`: `git switch -c spike --no-track origin/main` (or `git branch --no-track spike origin/main`). The branch starts at the same commit but gets no `branch.spike.remote` or `branch.spike.merge`, so `git status` reports no ahead/behind and a bare push refuses until you set a destination explicitly.
  • What does branch.autoSetupRebase do alongside it?
    It decides whether branch creation also writes `branch.<name>.rebase = true`, which makes `git pull` on that branch rebase rather than merge. Its values select which start points trigger it. Teams wanting rebase-style pulls generally set `pull.rebase` globally instead, since that also covers branches that already exist.

saying these in an interview costs you the question

  • Thinks it controls how git pull merges or rebases
  • Believes every new branch tracks something by default
  • Says the setting lives on the server
  • Confuses it with push.default or pull.rebase
  • Cannot name --track or --no-track as overrides

context