Chapter 03Lesson 01~150 minutes

Projects, Repository Settings, Visibility, Forks, Protected Resources, and Project Templates: Concepts, Architecture, and Mental Model

Build a precise mental model of GitLab projects as namespace-scoped hosted containers around Git repositories, and separate repository state from visibility, templates, forks, protected refs, and project lifecycle policy.

ProjectsNamespacesVisibilityForksProtected refsTemplates

Learning objectives

  • Explain why a GitLab project is broader than a Git repository and identify which state belongs to Git versus GitLab.
  • Relate namespace, project path, repository, default branch, visibility, feature toggles, forks, templates, and protected refs without collapsing them into one concept.
  • Explain how initialization, README/license/template choices create Git history and therefore affect later local-repository integration.
  • Distinguish archive, rename, transfer, export/import, deletion, and restoration by reversibility and downstream impact.
  • Inspect a project read-only through the UI, Git, glab, and REST API before changing project configuration.
Availability baseline (verified 2026-08-21). Project creation, blank projects, forks, private/public visibility, basic protected branches/tags, archiving, and the Projects API are available across Free, Premium, and Ultimate on GitLab.com, Self-Managed, and Dedicated. Internal visibility is not available for new GitLab.com projects; it remains available on Self-Managed and Dedicated. Group custom project templates are Premium/Ultimate. Project topics are currently documented as Beta. Exact UI labels and administrator restrictions can vary by GitLab version and instance policy.

1. A project is a governance boundary, not just a remote repository

After Chapters 01 and 02, you know where GitLab runs and how identities authenticate. The next production question is: what exactly are you creating when you click New project? A Git repository stores commits, trees, blobs, tags, and refs. A GitLab project wraps a repository in hosted state: a namespace path, visibility policy, members and inherited access, issues/work items, merge requests, CI/CD configuration and history, registries, security features, webhooks, deployment metadata, and project settings.

This distinction prevents a common beginner error. Running git clone copies repository history and refs; it does not clone GitLab membership, issue state, protected-branch policy, CI variables, webhooks, container images, or billing/namespace ownership. Conversely, changing a project description or visibility does not create a Git commit.

2. Namespace → project → repository → refs: the core mental model

Project boundary and state ownership
flowchart LR
NS[Namespace
personal/group] --> P[GitLab project
path + policy + hosted features]
P --> R[Git repository
objects + refs]
R --> B[branches/tags]
P --> H[hosted metadata
issues/MRs/settings]
P --> C[CI/CD + registries]
POL[visibility + roles + protected-ref policy] --> P
F[fork project
separate namespace/project] -. fork relationship .-> P

The namespace determines the project address and an important ownership/inheritance boundary. The project owns hosted configuration. The repository inside it owns Git history. Branch and tag protection are GitLab policy around refs; they are not new Git object types. A fork is another GitLab project with its own namespace and settings plus a recorded relationship to an upstream project.

3. Project identity: name, slug, path, ID, and namespace

Field What it means Why DevOps cares
Name Human-facing project name. May change without being the stable machine identifier you should rely on.
Slug / path URL-safe segment under the namespace. Appears in web, clone, package, registry, webhook, and integration addresses.
Path with namespace For example team/payment-api. Makes the target unambiguous across groups and users.
Project ID Numeric GitLab identity. Useful for APIs because it survives many display-name changes.
Namespace Personal namespace or group/subgroup that contains the project. Controls ownership context, inheritance, transfer destination, and often governance.

4. Visibility is hosted authorization, not Git cryptography

Visibility determines who can discover and access a project through GitLab. It does not encrypt Git objects. On GitLab.com, new projects are effectively chosen between Private and Public; the Internal level is documented for Self-Managed and Dedicated, where authenticated non-external users can access internal resources subject to policy.

Visibility Who can generally see/clone Offering note
Private Members with sufficient repository access. All offerings.
Internal Authenticated internal users, except external users, subject to instance policy. Self-Managed and Dedicated; not available for new GitLab.com projects.
Public Anyone, including unauthenticated users, unless an administrator restricts public access. All offerings; use deliberately because code and hosted metadata can become internet-visible.
Security invariant: before changing visibility, inventory not only source files but issues, merge requests, pipeline/job visibility, artifacts, wiki/snippets, releases, and any metadata that could become reachable. A repository that contains no secret today can still contain sensitive history.

5. Initialization choices can create the first Git history

A blank project with no repository commit is different from a project initialized with a README, license, or template. Selecting Initialize repository with a README creates the default branch and a first commit on the server. If you already have an unrelated local repository with its own first commit, pushing or pulling without planning can produce a non-fast-forward rejection or an unrelated-histories situation.

The safest production pattern is to declare the source of truth before project creation: either start hosted-first and clone that history, or create an empty GitLab project and push the existing local history. Do not independently initialize both sides and hope Git will infer that they belong together.

6. Forks, copies, imports, and templates preserve different relationships

Mechanism Repository/history result Hosted relationship / copied state
Fork Copies upstream repository, optionally all branches or only default branch. GitLab records an upstream fork relationship; issues/MRs/wiki are not simply cloned as part of the fork.
Built-in project template Starts from template content/history provided by GitLab. Creates an independent project; useful for scaffolding, not continuous upstream synchronization.
Group custom project template Copies exportable project state from a template project. Premium/Ultimate; copied permissions/sensitive objects depend on creator permissions.
Import/export Migrates supported project data/history. Migration operation, not a live synchronization relationship.
Independent Git copy You can clone and push repository history elsewhere. No GitLab fork relationship or automatic hosted-state transfer.

7. Protected branches and tags are policy around refs

A protected branch is still an ordinary Git branch ref. GitLab evaluates hosted authorization before accepting certain pushes, deletes, force-pushes, or merges. Protected tags similarly control who may create protected tag names and help prevent accidental update/deletion. Basic protected branches and protected tags are available on Free; finer-grained user/group and Code Owner controls are tier-dependent.

Current GitLab documentation exposes protected-branch configuration through Settings → Repository → Branch rules; the older dedicated Protected branches settings are being removed. That is exactly why the course teaches the policy model before memorizing a menu path.

8. Project lifecycle operations have different blast radii

Operation Reversibility / effect Production question
Rename path Redirects may help temporarily, but remotes and integrations can still need updates. Which scripts, webhooks, packages, badges, registries, deploy references, and docs embed the old path?
Transfer Moves the project to another namespace; access/inheritance and paths may change. Does destination ownership and membership match the intended governance model?
Archive Makes most project features read-only, removes fork relationships, stops scheduled pipelines and pull mirroring. Is preservation/read-only state sufficient instead of deletion?
Delete / pending deletion Schedules destructive removal; restoration is possible while pending under current behavior. Have you exported evidence and verified there is no valuable data?
Export/import Copies supported project data for migration/backup-like workflows. What is excluded and how will identity/permissions be verified after import?

9. Read-only inspection before configuration

Use several surfaces because each proves something different. The web UI is useful for human-readable settings; glab gives structured command output; Git proves local/remote ref state; the REST API exposes machine-readable project metadata.

# Replace with a project you can safely inspect.
FULL_PATH="your-namespace/your-project"

# Hosted project metadata through glab.
glab repo view "$FULL_PATH" -F json   --jq '{id,path_with_namespace,visibility,default_branch,archived,topics}'

# Find the numeric project ID once, then make the target explicit.
PROJECT_ID="$(glab repo view "$FULL_PATH" -F json --jq .id)"
glab api "projects/$PROJECT_ID"   --jq '{id,path_with_namespace,visibility,default_branch,archived,empty_repo,topics}'

# Git answers a different question: which remote URL and refs exist locally?
git remote -v
git branch -vv
git ls-remote --heads origin

A missing field is evidence, not permission to guess. For example, default_branch: null can be legitimate for an empty project. Likewise, an empty protected-branches list means no returned rules for that project/context; it does not prove an instance administrator cannot impose other controls.

10. Why these defaults become production dependencies

CI pipeline sources, branch rules, package coordinates, container registry paths, release URLs, webhook targets, environment policies, deployment scripts, and dashboards often reference project identity and default-branch assumptions. A project path that looks cosmetic on day one can be a production interface six months later. Treat creation defaults as architecture: document the owner, namespace, visibility, source-of-truth history, default branch, and lifecycle policy before automation depends on them.

Knowledge check

You clone a project and receive commits, but no GitLab issues or CI variables. Is the clone incomplete?

A branch is “protected.” Did Git create a new protected-branch object in the repository?

Why can “Initialize with README” be dangerous when you already have a local repository?

A learner on GitLab.com cannot select Internal visibility. Is that necessarily a permissions bug?

Summary

A GitLab project is a namespace-scoped hosted container around a Git repository, not a synonym for the repository itself. Visibility, feature settings, forks, templates, protected refs, archive/delete state, and namespace ownership live in GitLab. Initialization choices can create real Git history. Production-safe project creation therefore starts by identifying the source of truth, owner, namespace, visibility, default branch, and downstream path dependencies before clicking Create.

Official references

Next lesson

Create and prove a disposable project

Lesson 2 turns the mental model into a small GitLab.com Free workflow with before/after inspection through UI, Git, glab, and the Projects API.

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
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.