Chapter 07Lesson 01~75 minutes

Remotes, Refspecs, Fetch, Pull, Push, SSH, HTTPS, and Protocol Behavior: Concepts, Architecture, and Mental Model

Demystify remotes by separating local remote names, remote repositories, remote-tracking refs, refspec mappings, upstreams, remote HEAD, pull integration, and SSH/HTTPS authentication boundaries.

Remote refsRefspecsUpstreamsSSH / HTTPS

Learning objectives

  • Distinguish a configured remote name from the independent repository it reaches.
  • Explain local branches versus remote-tracking refs and how fetch refspecs connect them.
  • Read push refspecs as explicit local-source to remote-destination mappings.
  • Explain upstream tracking, remote HEAD, and pull as fetch plus integration.
  • Separate transport authentication/authorization from commit author identity.

1. The problem — “remote” is several different things at once

Chapter 06 made branches concrete: a branch is a movable ref, and merging changes the commit graph. The moment a second repository enters the picture, beginners often blur three separate facts: a local nickname such as origin, the independent repository reached through that nickname, and local remote-tracking refs such as origin/trunk. Those are not interchangeable.

This chapter makes networked Git observable. You will learn what exists only in local configuration, what fetch updates locally, what push asks another repository to update, and why pull is not a new transfer primitive but a fetch followed by an integration choice.

2. A remote name is local configuration; the remote repository is independent state

A remote such as origin is normally a locally configured name associated with one or more URLs and fetch/push policy. The server or bare repository at that URL has its own object database and refs. Renaming your local remote from origin to central does not rename anything on the server.

git remote -v
git remote get-url origin
git config --get-regexp '^remote\.origin\.'

These commands inspect local configuration. By contrast, git ls-remote origin contacts the other repository and asks which refs it currently advertises, without updating your local branches or remote-tracking refs.

3. Local branches and remote-tracking refs are different movable names

A local branch such as refs/heads/trunk is yours to move through local commits, merges, and rebases. A remote-tracking ref such as refs/remotes/origin/trunk is your local record of where the remote branch was when Git last updated that record through fetch-like communication (and in some successful push cases).

Fetching origin can move origin/trunk without moving local trunk. That separation is the key to safe inspection: fetch first, compare, then decide whether and how to integrate.

4. Mental model — fetch and push move different refs in different repositories

Two repositories, three visible branch names
flowchart TD
L[local refs/heads/trunk] --> LC[local commit]
RT[local refs/remotes/origin/trunk] --> RC[locally stored remote-tip commit]
RR[remote refs/heads/trunk] --> SR[remote tip commit]
RR -->|git fetch origin maps source ref to local destination ref| RT
L -->|git push origin trunk asks remote to update its branch| RR
RT -. compare/integrate explicitly .-> L

The remote branch belongs to the remote repository. The remote-tracking ref belongs to your repository. A fetch maps advertised remote refs into configured local destinations; it does not automatically merge them into your local branch. A push sends needed objects and asks the receiving repository to update destination refs, subject to fast-forward rules, permissions, hooks, and server policy.

5. Fetch refspecs answer “which remote ref maps to which local ref?”

A refspec is a mapping written roughly as <source>:<destination>. A typical clone config contains:

+refs/heads/*:refs/remotes/origin/*

The source side means “remote branches.” The destination side means “store them under this local remote-tracking namespace.” The * is a pattern substitution. The leading + permits the remote-tracking destination to follow a remote branch even when that remote branch was deliberately rewritten and no longer fast-forwards from your previous observation.

git config --get-all remote.origin.fetch
git fetch origin

6. Push refspecs run in the opposite direction

For a push, the source is resolved in your repository and the destination is a ref in the receiving repository. An explicit form is:

git push --dry-run origin HEAD:refs/heads/release-candidate

This says: “take the commit reached by my current HEAD and propose updating the remote branch release-candidate.” A normal non-force push refuses a branch update that would discard remote history. The dry run is an important preflight because it negotiates the intended update without changing the receiving refs.

7. Upstream tracking is a relationship, not another branch

A local branch can have an upstream: the branch it normally compares with, pulls from, and—depending on push policy—pushes toward. For trunk tracking origin/trunk, the important local configuration is usually:

[branch "trunk"]
    remote = origin
    merge = refs/heads/trunk

Inspect it through Git rather than editing configuration by hand:

git branch -vv
git rev-parse --abbrev-ref --symbolic-full-name '@{upstream}'
git config --get-regexp '^branch\.trunk\.'

branch.trunk.merge names the branch on the remote side (refs/heads/trunk); the configured fetch refspec explains why the corresponding local observation is usually named origin/trunk.

8. Remote HEAD means “default branch” context, not your current branch

A bare/hosted repository has its own HEAD, commonly a symbolic ref naming its default branch. During clone, Git can use that advertised information to decide what to check out. Locally, a symbolic ref such as refs/remotes/origin/HEAD can represent your recorded idea of the remote's default branch.

git ls-remote --symref origin HEAD
git symbolic-ref -q refs/remotes/origin/HEAD
git remote set-head origin -a

Do not confuse origin/HEAD with “the latest commit on the remote.” It is a symbolic convenience pointing at one remote-tracking branch.

9. Pull = fetch + a chosen integration operation

git pull first fetches, then integrates the selected fetched branch into the current branch. The integration may be fast-forward-only, merge-based, rebase-based, or (where explicitly requested) squash-based. Because repository and user configuration can affect this choice, production runbooks should normally state it explicitly:

git pull --ff-only
git pull --rebase
git pull --no-rebase

--ff-only is especially useful in automation when a pull is allowed to advance a branch only if no local divergence exists. A rebase rewrites local commit identities and therefore requires the history-rewrite discipline introduced later in the course.

10. SSH and HTTPS are transport/authentication boundaries, not commit identity

Concern SSH transport HTTPS transport
Server identity SSH host-key verification TLS certificate/hostname validation
User/client authentication Typically SSH keys/agent; server policy decides account mapping Credential helper, token/OAuth/password mechanism supported by server
Commit author identity user.name/user.email commit metadata — separate from transport authentication
Authorization Remote/server policy decides whether the authenticated principal may read/update specific refs
Do not put real tokens in tutorial URLs or logs. Use credential helpers or CI secret injection. Do not disable SSH host-key or HTTPS certificate verification merely to silence trust errors.

11. Read-only remote inspection ladder

git remote -v
git remote get-url origin
git branch -vv
git config --show-origin --show-scope --get-regexp '^(remote\.|branch\.|pull\.|push\.)'
git for-each-ref --format='%(refname) %(objectname:short)' refs/remotes/
git ls-remote --symref origin HEAD
git remote show origin

The first five are primarily local-state inspection. ls-remote and a normal remote show communicate with the remote, but they do not integrate fetched history into your branch. This distinction matters in CI diagnostics where you want evidence before mutation.

12. DevOps connection — non-interactive clones need explicit remote semantics

CI runners, release jobs, deployment controllers, and GitOps agents often have no human available to resolve a credential prompt or an unexpected merge. A reliable automation path therefore pins the repository/ref it expects, fetches deliberately, records exact object IDs, chooses integration rules explicitly, and separates read credentials from write credentials where possible.

13. Knowledge check

Question 1. Does git fetch origin normally advance your local trunk branch?

Question 2. Is origin a special server-side Git keyword?

Question 3. What does refs/heads/*:refs/remotes/origin/* describe?

Question 4. Does a successful SSH key login determine the Author: field in a commit?

Question 5. Why is git pull best understood as two phases?

14. Summary

Remote names are local configuration; remote repositories have independent refs; remote-tracking refs are local observations; fetch and push use refspec mappings in opposite directions; upstream tracking connects a local branch to its normal remote branch; pull is fetch plus integration; and SSH/HTTPS authenticate transport separately from commit identity.

Next

Watch refs move across a local bare remote

Lesson 2 builds a no-account laboratory with a bare repository and multiple working clones, then uses ls-remote, fetch, pull, push, upstream tracking, dry runs, and a guarded force update to prove each state transition.

Authoritative references

 git-fetch
 git-push
 git-pull
 git-remote
 Git data model

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.