Chapter 03Lesson 02~135 minutes

Creating Repositories, Templates, Settings, Visibility, Topics, and Default Branches: Guided Hands-On Workflow and Core Operations

Create and inspect disposable repositories, connect hosted state to local Git, modify safe repository metadata, and prove the difference between ordinary, template-derived, and forked repository relationships.

gh repoTemplatesTopicsState verification

Learning objectives

  • Create a disposable public repository with deliberate owner, visibility, description, and initialization choices using GitHub CLI or the web UI.
  • Verify repository identity, visibility, default branch, and permissions before cloning or pushing.
  • Connect hosted default-branch/ref state to a local clone, create a small commit, push it, and prove the exact commit OID on GitHub.
  • Edit non-destructive hosted metadata—description and topics—and verify that the Git commit OID does not change.
  • Create a disposable template repository, generate a derived repository, and prove that template provenance is not fork provenance.
  • Choose the correct GitHub surface or control from the resource model instead of memorizing one creation sequence.
Availability: Required workflow uses GitHub.com + GitHub Free + public disposable repositories, Git, and current GitHub CLI. If your account or organization policy prevents public repository creation, use private disposable repositories you control; skip any public-discovery observation. Internal visibility is not required.

1. Scenario: provision three disposable Atlas repositories

You are creating a tiny service called Atlas Echo. The lab uses three repositories in your personal namespace: a normal project repository, a template repository, and a repository generated from that template. Every name contains a timestamp so repeated runs do not collide.

The important part is not speed. Before every mutation you will state which resource changes: GitHub repository metadata, a Git ref/commit, or local Git configuration. Afterward you will verify through a different interface.

Disposable-only: all repositories in this lesson contain synthetic text and must be deleted after Lesson 05 or earlier if you stop. Do not reuse a production repository for the exercises.

2. Preflight: prove identity and tooling first

git --version
gh --version
gh auth status --active --hostname github.com
OWNER=$(gh api /user --jq .login)
printf 'GitHub owner: %s\n' "$OWNER"

The active GitHub CLI account is the default owner when gh repo create receives only a repository name. We still capture OWNER and use OWNER/REPO explicitly so the target is unambiguous.

Role assumption: your personal account may create repositories in its own namespace. Creating in an organization requires separate repository-creation permission and may be limited by organization/enterprise policy.

3. Create unique lab names and predict the first state change

Git Bash, Bash, or zsh

STAMP=$(date +%Y%m%d%H%M%S)
REPO="github-repo-model-$STAMP"
TEMPLATE="github-template-model-$STAMP"
DERIVED="github-derived-model-$STAMP"
printf '%s\n' "$OWNER/$REPO" "$OWNER/$TEMPLATE" "$OWNER/$DERIVED"

PowerShell

$OWNER = gh api /user --jq .login
$STAMP = Get-Date -Format yyyyMMddHHmmss
$REPO = "github-repo-model-$STAMP"
$TEMPLATE = "github-template-model-$STAMP"
$DERIVED = "github-derived-model-$STAMP"
"$OWNER/$REPO`n$OWNER/$TEMPLATE`n$OWNER/$DERIVED"

Prediction: creating $REPO with --add-readme will create a GitHub repository resource, one initial Git commit, one branch selected as default, and hosted description/visibility metadata. It will not create a local clone unless --clone is requested.

4. Create the normal repository deliberately

Use the CLI path below, or perform the equivalent choices in GitHub’s current New repository page: owner = your personal account, visibility = public (or private if policy requires), description = synthetic lab text, initialize with README.

gh repo create "$OWNER/$REPO" \
  --public \
  --description "Disposable GitHub repository-model lab" \
  --add-readme

Resource change: GitHub creates $OWNER/$REPO. Because --add-readme requests content, GitHub also creates the initial commit and branch. The command does not edit any pre-existing local Git repository.

If public creation is prohibited: replace --public with --private. Do not choose --internal unless you are intentionally operating inside an eligible Enterprise Cloud organization.

5. Verify creation through structured hosted state

gh repo view "$OWNER/$REPO" \
  --json nameWithOwner,visibility,defaultBranchRef,description,isEmpty,viewerPermission \
  --jq '{nameWithOwner,visibility,defaultBranch: .defaultBranchRef.name,description,isEmpty,viewerPermission}'

gh api -H "X-GitHub-Api-Version: 2026-03-10" \
  "/repos/$OWNER/$REPO" \
  --jq '{full_name,visibility,default_branch,archived,is_template,permissions}'

Expected observations: the full name matches the intended owner/name, visibility matches your creation choice, defaultBranchRef.name is populated because the README created history, and your viewer permission is sufficient to administer your personal repository. If any owner or visibility value is wrong, stop before adding more state.

Notice that the API result is a repository resource, not a Git commit. You will verify the commit separately.

6. Clone and connect hosted state to local Git

gh repo clone "$OWNER/$REPO"
cd "$REPO"
git remote -v
git branch --show-current
git status --short --branch
git log --oneline --decorate -3
LOCAL_HEAD=$(git rev-parse HEAD)
REMOTE_HEAD=$(git ls-remote origin HEAD | awk '{print $1}')
printf 'local=%s\nremote=%s\n' "$LOCAL_HEAD" "$REMOTE_HEAD"
test "$LOCAL_HEAD" = "$REMOTE_HEAD"

The clone gives you a separate local Git repository. origin is local configuration pointing at GitHub. Matching OIDs prove the local checked-out commit and GitHub’s advertised HEAD currently identify the same Git object. This does not mean GitHub metadata was cloned into .git.

7. Make one local commit, push it, and verify causality

printf '%s\n' 'service=atlas-echo' > service.env.example
git add service.env.example
git commit -m "docs: add synthetic service marker"
NEW_OID=$(git rev-parse HEAD)
git push origin HEAD
HOSTED_OID=$(gh api -H "X-GitHub-Api-Version: 2026-03-10" \
  "/repos/$OWNER/$REPO/commits/$(git branch --show-current)" --jq .sha)
printf 'local=%s\nhosted=%s\n' "$NEW_OID" "$HOSTED_OID"
test "$NEW_OID" = "$HOSTED_OID"

The commit operation changed only local Git first. The push then transferred objects and requested a hosted branch-ref update. The API GET independently confirms the branch now resolves to the exact commit you created. Hosted description/topics have not changed because Git content and hosted metadata are separate resource layers.

8. Change hosted metadata without changing Git history

Record the commit OID before changing description/topics:

BEFORE_META=$(git rev-parse HEAD)
gh repo edit "$OWNER/$REPO" \
  --description "Disposable Atlas Echo repository architecture lab" \
  --add-topic devops \
  --add-topic github-learning

gh repo view "$OWNER/$REPO" \
  --json description,repositoryTopics \
  --jq '{description,topics: [.repositoryTopics[].name]}'
AFTER_META=$(git rev-parse HEAD)
test "$BEFORE_META" = "$AFTER_META"

The description/topics changed the GitHub repository resource. The local commit OID stayed identical because no Git object or ref changed. This is a simple but important example of hosted metadata that automation can query without assuming it is version-controlled.

Topic privacy nuance: GitHub documents that topic names are public even when a topic is created from a private repository. Do not encode confidential project names or incident identifiers as topics.

9. Create a template repository with reusable starter content

Return to the parent directory and create a second disposable repository. A template repository is an ordinary repository with a hosted template flag; its Git data is still ordinary Git data.

cd ..
gh repo create "$OWNER/$TEMPLATE" --public --add-readme --clone
cd "$TEMPLATE"
mkdir -p .github
printf '%s\n' '# Atlas Service Template' '' 'Replace this text in generated projects.' > README.md
printf '%s\n' 'SERVICE_NAME=replace-me' > .env.example
printf '%s\n' 'node_modules/' '.env' > .gitignore
git add README.md .env.example .gitignore
git commit -m "chore: prepare disposable service template"
git push origin HEAD
cd ..
gh repo edit "$OWNER/$TEMPLATE" --template
gh repo view "$OWNER/$TEMPLATE" --json isTemplate,defaultBranchRef --jq '{isTemplate,defaultBranch: .defaultBranchRef.name}'

The first commit/update modifies Git content; gh repo edit --template changes hosted repository metadata. The verification must therefore check both layers when you care about both. Current GitHub CLI exposes --template on gh repo edit.

10. Generate a repository from the template and inspect provenance

gh repo create "$OWNER/$DERIVED" \
  --public \
  --template "$OWNER/$TEMPLATE"

gh repo view "$OWNER/$DERIVED" \
  --json nameWithOwner,isFork,parent,templateRepository,defaultBranchRef \
  --jq '{nameWithOwner,isFork,parent:(.parent.nameWithOwner // null),template:(.templateRepository.nameWithOwner // null),defaultBranch:.defaultBranchRef.name}'

gh repo clone "$OWNER/$DERIVED"
git -C "$DERIVED" log --oneline --decorate --all -5

Expected model: the generated repository is not a fork. GitHub records template provenance where exposed, and the generated repository starts its own history rather than sharing a fork network. GitHub’s current template documentation describes template-generated branches as having unrelated histories, so you should not plan to synchronize future template changes through ordinary upstream pull requests.

Do not confuse content similarity with lineage. Two repositories can begin with identical files and still have unrelated histories and different hosted relationships.

11. Compare template provenance with fork provenance

Question Generated from template Fork
Primary intent Start a new project from reusable structure/content. Develop/contribute relative to an upstream repository.
History relationship New/unrelated generated history. Includes upstream history and remains in a repository network.
Hosted relationship Template provenance may be visible; isFork=false. isFork=true with parent/upstream relationship.
Can later upstream changes be merged automatically because of template relation? No special merge lineage is created by the template relationship. Normal Git history can be fetched/merged from upstream subject to access/policy.
Visibility behavior Chosen for the generated repository subject to owner/policy. Fork visibility follows repository-network rules.

An informal “starter repository” can be any ordinary repository containing starter files. If reproducible project creation is the goal, template semantics are explicit and machine-readable. If ongoing upstream contribution is the goal, fork semantics are the relevant relationship.

12. Map each action to the correct GitHub surface

Need GitHub surface/control Underlying state
Change project description/topics Repository “About” metadata or gh repo edit. Hosted repository metadata; no Git commit.
Change README content Edit/commit/push through Git or GitHub file editor. Git tree/commit/ref state.
Change default branch Repository settings or gh repo edit --default-branch. Hosted setting pointing at an existing branch.
Create derived project baseline Template repository / gh repo create --template. New GitHub repository + generated Git history.
Contribute relative to upstream Fork. Repository-network relationship + Git history.

13. Challenge: choose the control before seeing the command

  1. A platform team wants every new microservice to begin with the same CI skeleton but then diverge independently. Choose template, fork, or ordinary copy and justify the relationship.
  2. A contributor wants to propose changes back to an upstream open-source project. Choose template, fork, or ordinary repository.
  3. A repository’s description says “old service name,” but Git history is correct. Decide whether a commit is necessary.
  4. A new hosted repository contains a README, while your local project already has its own initial commit. Before forcing anything, state which two histories now exist and what evidence you need.

14. Verification checklist

  • Normal repository owner/name, visibility, and default branch match the intended design.
  • Local and hosted branch OIDs matched after the push.
  • Description/topics changed without changing the Git commit OID.
  • Template repository reports isTemplate=true.
  • Derived repository reports isFork=false and is explainable as a new project baseline.
  • No real credentials, secrets, or proprietary content were stored in any disposable repository.
  • You can point to the exact resource layer changed by each CLI command.

Knowledge check

After gh repo edit --description, should git rev-parse HEAD change?

Why did the lab compare local and hosted commit OIDs after push?

A generated repository says isFork=false. Is that consistent with being created from a template?

Which is safer when you already have a meaningful local history: remote README initialization or an empty remote?

A team needs ongoing synchronization with upstream history. Should it depend on template provenance?

15. Summary

You have now created and verified repository state across three layers: hosted repository resource metadata, Git refs/commits, and local clone configuration. You also proved that changing metadata does not change history and that template generation is a different provenance model from forking.

The next step is to choose these controls deliberately before production dependencies form. Ownership, visibility, initialization, default branches, and merge methods all trade convenience against governance and compatibility.

Next lesson

Choose repository defaults by operating model

Lesson 03 compares remote versus local initialization, template versus fork/starter patterns, visibility and ownership, default-branch policy, and merge-method settings with a production decision table.

Authoritative references

 Creating a new repository
 gh repo create
 gh repo view
 gh repo edit
 Creating a template repository
 Creating a repository from a template
 Forks
 Classifying your repository with topics
 REST API endpoints for repositories
 REST API versions

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.