In Git, what is a stale remote-tracking branch and what does git remote prune do?
answer
- fetch adds, never removes
- pointers, not commits
- only the refs/remotes namespace
- there is a dry-run flag
- local branches show as gone
basics
~10 sA stale remote-tracking ref is one like origin/feature whose branch no longer exists on the remote; fetching never deletes it. git remote prune origin removes those refs, leaving your local branches and commits untouched.
solid answer
~40 sFetching adds and updates refs under `refs/remotes/origin/` but never deletes them, so when a branch is deleted on the remote your `origin/<branch>` lingers indefinitely — that is a stale remote-tracking branch. `git remote prune origin` deletes remote-tracking refs whose counterparts are gone, and `git remote prune -n origin` (or `--dry-run`) shows what it would remove first; `git remote show origin` also lists stale refs. The equivalent during a fetch is `git fetch --prune`, and `fetch.prune = true` makes it automatic. Pruning touches only `refs/remotes/`: your own local branches survive, and one whose upstream vanished shows as `gone` in `git branch -vv`, which you then delete yourself with `git branch -d`. Nothing is destroyed, because pruning removes pointers, not commits.
code
console · 9 lines$ git remote prune -n origin
Pruning origin
URL: https://example.com/team/app.git
* [would prune] origin/feature/old-checkout
$ git remote prune origin
* [pruned] origin/feature/old-checkout
$ git branch -vv
* main 1f3a9c2 [origin/main] release notes
feature/old-checkout 7b3d40e [origin/feature/old-checkout: gone] wipgo deeper
Know that deleted remote branches leave leftover entries like origin/feature in your listing, and that git remote prune origin clears them without touching your own branches.
Explain why fetch never deletes refs, which namespace pruning affects, how the dry-run flag helps, and that a local branch whose upstream vanished shows as gone and must be deleted deliberately.
Show you keep long-lived clones honest: automatic pruning on high-churn repositories, a periodic pass over branches marked gone, and the ability to explain why a ref survived a prune under a narrowed refspec.
Own the convention: decide whether pruning is on by default across the organisation, and weigh the cost of tooling that reads remote branch lists against clones that quietly drift out of date.
## Why stale refs accumulate A fetch applies the configured refspec, typically `+refs/heads/*:refs/remotes/origin/*`. That rule says which remote refs map to which local ones; it says nothing about refs that no longer exist upstream. So a fetch creates and updates remote-tracking refs but leaves orphans behind. On a busy repository where branches are created and deleted constantly, `git branch -r` grows into a list of long-dead names — noise in completion, in log output, and in anything scripted over remote branches. ## Pruning them `git remote prune <name>` queries the remote, compares its refs to what you have under `refs/remotes/<name>/`, and deletes those with no counterpart. Add `-n` or `--dry-run` to see the list before acting. `git remote show <name>` reports the same refs as stale, with a hint to prune. The equivalent at fetch time is `git fetch --prune`, and setting `fetch.prune = true` makes every fetch prune automatically — the usual choice on repositories with high branch churn. ## What pruning does not touch This is the part candidates get wrong. Pruning deletes only remote-tracking refs. Specifically: - Your local branches under `refs/heads/` are untouched, including one that was tracking the deleted remote branch. Its configured upstream now points at a ref that no longer exists, and `git branch -vv` marks it `gone`. Deleting it is a separate, manual decision — `git branch -d <name>` when merged, `-D` when not. - Your commits are untouched. Removing a ref only drops a pointer; anything still reachable from another ref or from the reflog remains. - Tags are untouched. Removing a tag that vanished upstream is a different operation. ## Diagnosing the common confusions The branch was deleted on the server but I still see it is almost always a missing prune, not a server problem. Conversely, prune deleted my work is almost never true: check `git branch` and the reflog and the local branch is still there. A third case is a ref that stays after pruning because the remote genuinely still has it — useful evidence when someone believes a cleanup happened and it did not. ## Interaction with narrowed refspecs Pruning is evaluated against the refspec, so a remote narrowed with `git remote add -t main` or `git remote set-branches` prunes only within what that refspec covers. If you previously fetched wildcard-style and then narrowed the configuration, refs fetched under the old rule can survive a prune because they now fall outside the mapping. Deleting them explicitly with `git branch -r -d <remote>/<branch>` is the direct fix. ## Practical hygiene On a repository where topic branches are short-lived, enabling `fetch.prune` keeps the local view honest with zero effort and makes remote-branch listings usable again. Pair it with an occasional pass over local branches marked `gone`, which is the one part Git deliberately leaves to you — those branches may hold commits that were never merged anywhere.
- Does pruning risk losing commits?No. A prune deletes remote-tracking refs, which are pointers to commits you already have. Any commit still reachable from a local branch, a tag or the reflog survives untouched, and the reflog keeps unreachable ones around for its expiry window. Losing work would require deleting the local branch as well.
- After pruning, git branch -vv shows a local branch marked gone. What now?Its upstream no longer exists, usually because the branch was merged and deleted upstream. Confirm it holds nothing unmerged, then delete it with git branch -d, which refuses if commits are unmerged. Use -D only when you are sure the work is expendable or already delivered elsewhere.
- How do you make pruning automatic?Set fetch.prune to true, so every fetch removes remote-tracking refs whose upstream counterparts are gone. It is the usual setting on repositories with heavy branch churn, and it only affects the refs/remotes namespace, so it never deletes local branches or commits.
saying these in an interview costs you the question
- Thinks git remote prune deletes local branches
- Believes fetch removes refs for deleted remote branches
- Fears pruning destroys commits
- Confuses pruning refs with garbage collecting objects
- Assumes a deleted upstream branch cleans up its local counterpart