Skip to content
GitTree

Lesson 10 · Everyday work

Connect a remote without confusing it with an upstream

Add a local bare origin, fetch its main branch and deliberately choose what local main tracks. Prove that a remote name, a remote-tracking ref and an upstream setting are three different things.

Progress saved in this browser.

Playing loads the video from YouTube (privacy-enhanced mode).

English narration · English and Arabic captions

Open the video pageWatch on YouTube

What you will learn

  • Distinguish origin, origin/main and main's upstream configuration.
  • Explain what adding a remote, fetching and selecting an upstream each change.
  • Connect GitTree to a real local bare repository without provider credentials.
  • Prove that the feature branch remains local and unpublished.

Before you start

Start where lesson 9 ended, in the original gittree-features: checked-out feature/pricing-cards has its workflow-card commit F1; main has five commits through the history document H5. Both are clean, no remote exists and dist remains ignored. These are demo refs, never instructions to change this website's branch.

The video was recorded with Git 2.52.0 and GitTree 2.0 on Ubuntu 24.04: the document, the remote, the fetch and the upstream were done in the app; the bare destination, the add-only state and the checks were run in the terminal. Nothing was run on macOS or Windows, and Ubuntu is the only Linux system recorded; the Command-key chords below come from the app's keymap. GitTree's inspected Git floor is 2.39.0. Once you are signed in, local Git transport and upstream configuration are on the Free plan; provider integration is a different gated feature.

Reserve one empty sibling destination gittree-features-origin.git outside every source checkout. Do not replace an existing directory. The bare repository will be seeded from this project's main; it is not a GitLab installation, GitHub repository, backup service or CI runner. If the clone destination exists, stop and identify it rather than deleting it.

For the add-only prediction, background fetch must be off in this recording repository. Open Preferences with Command+, (Ctrl+, on Ubuntu), choose the gittree-features page under the repository's own name, and in Auto-fetch interval enter 0, then Apply, wait for Saved, and Exit Preferences. The app stores this in its own per-repository settings, not in Git's config. Note the previous value to restore it later; do not change the app-wide interval or another repository.

Concept

A remote is repository-local configuration naming a transport address and fetch rules. origin is a convention, not a built-in central authority. Adding it writes this demo's config; it does not contact the address, create the destination or upload a branch.

A remote-tracking ref such as refs/remotes/origin/main is a local record updated by fetching. It is not the server branch refs/heads/main itself. Immediately after adding origin, there is no origin/main here. Fetch obtains the objects/refs but does not switch HEAD, merge, rebase or replace the working page.

An upstream is a relationship stored for a local branch. Here branch.main.remote = origin and branch.main.merge = refs/heads/main. Selecting it tells later commands which fetched branch main tracks. It does not create a commit, fetch missing history or publish feature/pricing-cards.

The analogy is an address book entry, the last message you collected, and a choice of which conversation to follow. They are related, but saving an address is not receiving or sending a message.

State effects

ActionWorking tree / indexLocal refs/configServer
Switch to mainSelect H5's recorded filesHEAD attaches to mainUnchanged
Commit the documentIndex/work agree with H6main advances to H6Unchanged
Prepare the bare copyOriginal unchangedOriginal has no origin yetSeparate local main starts at H6
Add Remote…Unchangedorigin URL/fetch config onlyUnchanged
Fetch AllUnchangedorigin/main becomes H6; objects obtainedRead, not modified
Set Upstream…Unchangedmain's remote/merge config setUnchanged

F1 stays on the local feature. The main/feature graph now has one distinct commit on each side of H5: documentation on main, workflow cards on feature. Neither is a merge.

Full project change

Switch to main before creating this file. Create docs/remotes.md with the full UTF-8/LF body and final newline:

File excerpt · markdown
# GitTree Features remotes

origin names a separate local bare repository used only for this course.
Its file:// URL is a transport address, not a GitLab project or a login.
main tracks origin/main after an explicit fetch and upstream selection.
origin/main is a local record of the last fetched remote main.
Adding a remote does not fetch, push or publish any branch.
feature/pricing-cards remains local and has no upstream in this checkpoint.
No credentials or machine-specific absolute paths are stored in this document.

Commit subject: docs: record remotes-and-upstreams practice. Author/committer: GitTree Demo <demo@example.com>. No second practice notebook or extra commit belongs in this checkpoint.

In GitTree

  1. In the original tab, right-click local main → Checkout main. Expect the history-document-era page, no workflow section, and clean status. If a dirty-switch dialog appears, Cancel and inspect the unexpected work.
  2. Open the palette with Command+Shift+P (Ctrl+Shift+P on Ubuntu). Choose New File…. In Path from the project folder, type docs/remotes.md, then Create. Paste the full body above and Save / Command+S. Wait for disk-save completion.
  3. Choose Back to Graph, then palette Show Working Changes. Review docs/remotes.md and activate Stage File. Enter the exact subject in Summary, leave Description empty and ordinary optional behaviors off. Click Commit Changes to 1 File once, or Command+Enter as an alternative. Verify the actual sixth main commit.
  4. Prepare the separate bare repository using terminal segment T1 below. This is an explicitly labeled native preparation step: no GitTree “create hosting project” button is invented.
  5. Run T2 to obtain the actual file:// URL. The inspected GitTree URL parser accepts file URLs, not a plain bare filesystem path even though native Git can accept one. Use the generated URL, with any spaces percent-encoded. Never paste a shell command into the remote URL field.
  6. Palette Add Remote… opens Add a remote. Enter Name = origin and URL = the measured file URL. Choose Add Remote. The add form has no separate Push URL field; that belongs to Edit Remote…. Expect origin configured, but no fetched origin/main yet.
  7. Fetch from the palette with Fetch All (Command+Shift+F, Ctrl+Shift+F on Ubuntu). Before this first fetch the side panel's Remote group does not list origin at all, so there is no row to right-click; with exactly one remote, Fetch All fetches it. Wait for the actual result. Expect origin/main at the same real SHA as main; HEAD and files stay put.
  8. Right-click local main, open the Upstream submenu and choose Set Upstream…. In What should main track?, select Upstream branch = origin/main, then Track. This named-ref action is not a generic palette command. Cancel leaves the relationship unchanged; do not choose Track Nothing.
  9. Verify with T3 and T4. Leave main checked out, feature/pricing-cards present but unpublished, and no in-progress operation. Do not press Push, Pull, Force Push… or a remote-delete command to “finish” connecting.

Ordinary options off means Amend Previous Commit unchecked; Skip Hooks, Add Signed-off-by, Different Author, Push After Commit and Allow Empty Commit off; no co-authors. Wait for confirmed completion rather than clicking twice.

In the terminal

Run all commands inside the isolated gittree-features, not a source checkout. App/native mutations are alternatives, not steps to repeat after app success.

T1 — record the document and prepare only main on the local origin

After saving the full document on main:

Command · bash
git switch --quiet main
git add -- docs/remotes.md
git commit --quiet -m "docs: record remotes-and-upstreams practice"
git clone --quiet --bare --single-branch --branch main --no-local . ../gittree-features-origin.git

All commands succeeded silently in the native fixture. The clone creates a new, separate bare repository from main only; it does not configure origin in the original. --no-local avoids a hardlinked local object-copy shortcut. There is no push in this preparation transcript.

If the app already committed the document, omit the first three commands. Never make the same document commit twice.

T2 — add, then fetch, then select upstream

Generate a real platform-correct, percent-encoded URL:

Command · bash
ORIGIN_URL="$(node --input-type=module -e "import path from 'node:path'; import {pathToFileURL} from 'node:url'; console.log(pathToFileURL(path.resolve('../gittree-features-origin.git')).href);")"
printf '%s\n' "$ORIGIN_URL"

The actual output is a machine-specific file URL ending /gittree-features-origin.git. Its root varies; file://<lab-root>/gittree-features-origin.git is explanatory notation, not fabricated terminal output or a literal URL to paste. ORIGIN_URL is a shell variable, not a credential.

Command · bash
git remote add origin "$ORIGIN_URL"
git config --get remote.origin.fetch
git for-each-ref --format='%(refname)' refs/remotes/origin

The add is silent. The config query prints:

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

The final for-each-ref prints nothing: adding a remote did not fetch one.

Command · bash
git fetch --quiet origin
git branch --set-upstream-to=origin/main main

Fetch succeeded silently. Actual upstream output:

Output
branch 'main' set up to track 'origin/main'.

T3 — prove the original's final state

Command · bash
git symbolic-ref --short HEAD
git rev-parse --abbrev-ref 'main@{upstream}'
git rev-list --left-right --count main...origin/main
git log -1 --format=%s origin/main
git rev-list --count main
git status --short

Outputs from the first five queries, in order:

Output
main
origin/main
0	0
docs: record remotes-and-upstreams practice
6

The final short status is empty, exit 0. The tab between the two zeros separates commits reachable only from main and only from origin/main; matching tips are not proof future fetches are unnecessary.

T4 — distinguish the actual bare repository from its local tracking ref

Command · bash
git --git-dir=../gittree-features-origin.git rev-parse --is-bare-repository
git --git-dir=../gittree-features-origin.git for-each-ref --format='%(refname)' refs/heads
git ls-remote --heads origin refs/heads/feature/pricing-cards
git config --get branch.feature/pricing-cards.remote

The first query prints true; the second prints refs/heads/main. The third is silent, exit 0: feature/pricing-cards was not published. The fourth is silent, exit 1: no feature upstream setting exists. That expected absence is not a failed fetch.

Independently resolve the three tips:

Command · bash
git rev-parse refs/heads/main
git rev-parse refs/remotes/origin/main
git --git-dir=../gittree-features-origin.git rev-parse refs/heads/main

All three actual SHAs agree. Never substitute H6 for their real SHA output.

Result

Where you end: checked-out main has six commits, including only the new docs/remotes.md. A separate local bare origin has main at the same H6. The original has origin configured and refs/remotes/origin/main fetched; main tracks origin/main. Index/work clean; ignored dist may remain. Local feature/pricing-cards still points at F1 and has no upstream or server branch. No merge, pull, hosted project, sign-in or CI run happened.

Common mistakes

  • Treating origin as a special server: it is a chosen local name.
  • Expecting Add Remote to create a server or fetch its branches.
  • Pasting a plain path into GitTree's URL field: generate the file URL instead.
  • Choosing a real company's remote, using a token-bearing URL, or reusing an existing bare directory.
  • Creating the document while still on the feature: it would record the wrong branch's history.

If something goes wrong

Before fetching, native upstream selection fails because origin/main does not exist. The isolated changed-input replay actually ran:

Command · bash
git -c advice.setUpstreamFailure=false branch --set-upstream-to=origin/main main

Observed stderr, exit 128:

Output
fatal: the requested upstream branch 'origin/main' does not exist

The branch tip and work remain unchanged. According to the app's source (not filmed), the upstream form instead has no fetched options and its Track control is unavailable with There are no remote-tracking branches yet. Fetch first. Do not draw the native fatal message as an app dialog. Fetch the intended remote, then deliberately select origin/main. In this lesson that is Fetch All.

A missing local directory, wrong URL or permissions failure is not fixed by forcing a push or disabling security. Cancel, inspect Edit Remote…, verify the actual destination and retry the intended fetch only. If there is already an origin, inspect it; do not overwrite or remove it blindly. Removing a remote changes local config/tracking, not the server itself, and is unnecessary for the canonical lesson.

Check your understanding

Answer each question, then read why. Questions marked “Required” count toward completing the lesson.

  1. Question 1 of 6

    You have just added origin. What is origin?

    Choose one answer.

  2. Question 2 of 6

    Which statements are true for this lesson?

    Choose every answer that applies.

  3. Question 3 of 6
    Required

    After adding origin, you fetch and set main's upstream. The page has no workflow section on main. What should happen to it?

    Choose one answer.

  4. Question 4 of 6
    Required

    Change the input: add origin but skip fetch. Try selecting origin/main as upstream. What happens?

    Choose one answer.

  5. Question 5 of 6

    A bare folder exists, but GitTree rejects the plain path pasted into URL. What is the correct next step?

    Choose one answer.

  6. Question 6 of 6
    Required

    Which evidence is required together?

    Choose every answer that applies.

0 of 6 correct

Answer the required questions correctly to complete the lesson.

Checked in this browser.

Practice

Explain why origin/main is absent immediately after Add Remote. In a separate same-project replay, try selecting it before fetching, then fetch and select it successfully. Verify main's SHA and complete index.html bytes did not change across either configuration action. At the original, prove main/origin/main agree and the feature is still absent from the bare server.

Your own confirmation: the site cannot see your computer.

To complete the lesson, answer the required questions correctly and confirm the practical exercise.

Recap

  • A remote configures an address; fetch obtains its refs; an upstream chooses a branch relationship.
  • origin/main is local fetched knowledge, not the server branch itself.
  • Connecting main did not publish the feature or change its working page.

Glossary terms introduced

Remote — مستودع بعيد; remote-tracking ref — مرجع تتبُّع بعيد; upstream — الفرع المتتبَّع; bare repository — مستودع مجرد; fetch — جلب; transport — وسيلة نقل.

Video transcript

The narration of the video, cue by cue.

Show the transcript
  1. Connect a remote, then choose an upstream deliberately.
  2. The feature exists locally; it has not been published.
  3. Disable background fetching only in this recording repository.
  4. Switch to main before writing the transport document.
  5. Save the complete document without machine-specific paths or credentials.
  6. Stage the transport document on main, not on the feature.
  7. The document adds the sixth commit on main.
  8. Prepare a separate bare copy of main for local transport.
  9. This destination has main, but no feature branch.
  10. The original and bare destination are separate repositories.
  11. Generate a file URL for the intended local destination.
  12. Saving the address does not fetch branches or upload the feature.
  13. Open the remote dialog in the original repository.
  14. Name it origin and verify the complete destination.
  15. The remote is configured; its branch has not been fetched.
  16. The fetch rule exists while the tracking-ref query is empty.
  17. Selecting a missing upstream fails without moving main.
  18. Does choosing an upstream replace fetching? It does not.
  19. Fetch the remote's main without switching your current branch.
  20. Origin slash main is your local fetched record.
  21. Fetching is not merging, rebasing or replacing the page.
  22. Choose the relationship for the named local main branch.
  23. Selecting the option alone is not the confirmed relationship.
  24. Confirm main's upstream without moving its commit.
  25. Verify main, its upstream, matching tips and clean work.
  26. An empty server feature query does not mean the local feature was lost.
  27. Address, fetched record and upstream setting remain different things.
  28. Correct an upstream choice without resetting the history.
  29. Verify the original and server separately before continuing.
  30. Explain why the missing ref required a fetch, not a push.
  31. A local bare remote is not a hosted project or a pipeline.
  32. Next, fetch a teammate's update while keeping your own files unchanged.