| |

GitHub 04 ๐ŸŒ Creating and Initializing a Repository (Public vs Private)

โฑ๏ธ Estimated read: 10 min | |

A repository is the container that holds a project’s files and their complete revision history. Creating one on GitHub is a four-step form: name it, choose who can see it, optionally seed it with starter files, and click create. The visibility choiceโ€”public or privateโ€”is the only decision that cannot be changed without consequences, and the consequences are asymmetric.

This chapter covers the repository creation workflow from the web UI and the GitHub CLI, the distinction between public and private visibility, and the initialization options that determine whether the repository starts empty or with a README, .gitignore, and license. It assumes the account and authentication setup from the previous chapters.


Key point: A repository created without starter files is completely empty. It has no commits, no branches, and no README. Cloning it produces an empty directory with a .git folder and a warning that you have cloned an empty repository.


Why visibility is the decision that matters

The public default. A public repository is visible to anyone on GitHub, and anyone can clone it, fork it, and read its entire history . This is the correct choice for open-source projects, portfolios, and anything intended to be shared. The code is not just visible; it is forkable, which means the history travels with it.

The private default. A private repository is visible only to the owner and the collaborators who are explicitly invited . This is the correct choice for proprietary code, work in progress, and anything that contains secrets, customer data, or unreleased features.

The one-way visibility trap. Visibility can be changed later in the repository settings, but the change is not symmetric. Switching a private repository to public exposes its entire history, including any secrets that were committed and later removed . The commit that contained the secret is still in the history, and anyone who clones the now-public repository can retrieve it. The rule is: if there is any doubt, start private. Making a public repository private is safe from a secrecy perspective, but it detaches forks and erases stars and watchers .

The organization restriction. In an organization, the ability to change visibility may be restricted to organization owners . A repository created as public by a member may not be changeable to private without the owner’s intervention. The visibility choice at creation is the one the creator controls.


a. Creating a repository from the web UI

The creation page is reached from the + menu in the upper-right corner of any GitHub page, then New repository . The URL https://github.com/new goes directly to the form.

The form has four sections. The owner dropdown selects the personal account or an organization where the creator has permission to create repositories . The repository name is limited to 100 characters, and it becomes part of the URL. The description is optional and appears on the repository page. The visibility radio buttons select public or private .

The initialization options are the checkboxes below the visibility. A README creates a README.md with the repository name as the heading and a placeholder description. A .gitignore template adds a file that excludes common build artifacts for the selected language. A license adds a LICENSE file with the chosen open-source license . If none of these are checked, the repository is created with no commits and no files.

The sequence is:

1. Click + โ†’ New repository
2. Owner: your username or an organization
3. Name: my-project
4. Description: optional
5. Visibility: Public or Private
6. Add README: optional
7. Add .gitignore: optional
8. Choose a license: optional
9. Create repository

b. Creating a repository with the GitHub CLI

The gh repo create command creates a repository from the terminal. The interactive form asks for the name, visibility, and whether to clone the new repository locally. The non-interactive form uses flags.

# Interactive: prompts for name, visibility, and clone.
gh repo create

# Non-interactive: public repository, no clone.
gh repo create my-project --public

# Private repository, cloned locally.
gh repo create my-project --private --clone

# Repository in an organization.
gh repo create my-org/my-project --public

The CLI creates the remote repository on GitHub. The --clone flag clones it to the current directory, which is the equivalent of creating the repository on the web and then running git clone . Without --clone, the repository exists on GitHub only, and the local directory must be connected to it manually.


c. The empty repository and the first push

A repository created without starter files is completely empty. It has no default branch, no commit, and no files. The GitHub page after creation shows the two commands for connecting a local repository.

# Connect an existing local repository to the empty remote.
git remote add origin https://github.com/username/my-project.git
git branch -M main
git push -u origin main

The git branch -M main renames the current branch to main if it was created as master. The git push -u origin main pushes the local commits to the remote and sets the upstream tracking . If the local directory has no commits yet, the push fails with “src refspec main does not match any.” The fix is to commit first.

A repository created with a README already has a commit and a default branch. The clone command is the standard one, and the local repository starts with the README file.


Complete Example Session

# ============================================
# PART 1: THE WEB UI CREATION
# ============================================
# + โ†’ New repository
# Name: my-project
# Visibility: Private
# Add README: checked
# Create repository

# ============================================
# PART 2: THE CLI CREATION
# ============================================
gh repo create my-project --private --clone

# ============================================
# PART 3: THE EMPTY REPOSITORY
# ============================================
# Created without README or .gitignore.
# The page shows the connection commands.

git remote add origin https://github.com/username/my-project.git
git branch -M main
git push -u origin main

# ============================================
# PART 4: THE INITIALIZED REPOSITORY
# ============================================
# Created with README.
# The clone command works immediately.

git clone https://github.com/username/my-project.git

# ============================================
# PART 5: THE VISIBILITY CHECK
# ============================================
# Confirm the repository is private or public.

gh repo view username/my-project --json visibility

# ============================================
# PART 6: THE STARTER FILES
# ============================================
# README.md: project description.
# .gitignore: build artifacts.
# LICENSE: open-source terms.

# ============================================
# PART 7: THE LOCAL-FIRST ALTERNATIVE
# ============================================
# Create the repository locally first.

git init my-project
cd my-project
echo "# My Project" > README.md
git add README.md
git commit -m "Initial commit"
gh repo create my-project --private --source=. --push

# ============================================
# PART 8: THE VISIBILITY CHANGE
# ============================================
# Settings โ†’ Danger Zone โ†’ Change visibility.
# Warning: private โ†’ public exposes the full history.

# ============================================
# PART 9: THE ORGANIZATION CASE
# ============================================
# The owner dropdown selects the organization.
# The creator must have permission to create repos.

gh repo create my-org/my-project --private

# ============================================
# PART 10: THE FULL PICTURE
# ============================================
# Name, visibility, and starter files.
# Public: visible to all, forkable.
# Private: visible to owner and collaborators.
# Visibility change: private โ†’ public exposes history.

echo "Repository creation complete."

The ten parts walk through the web UI, the CLI, the empty repository, the initialized repository, and the local-first alternative. The pattern is consistent: the remote is created on GitHub, and the local repository is either cloned from it or connected to it.


Quick Reference

Creation Methods

MethodCommand / Path
Web UI+ โ†’ New repository or https://github.com/new
CLI interactivegh repo create
CLI flagsgh repo create name --private --clone
Local-firstgh repo create name --source=. --push

Visibility

VisibilityWho Sees ItTypical Use
PublicAnyone on GitHubOpen source, portfolios
PrivateOwner and collaboratorsProprietary, WIP

Starter Files

FileEffect
READMECreates README.md, initializes the repository
.gitignoreExcludes build artifacts for a language
LICENSEAdds open-source license terms

Visibility Change Consequences

ChangeConsequence
Private โ†’ PublicFull history exposed, including removed secrets
Public โ†’ PrivateForks detached, stars erased
Private โ†’ PublicAnyone can fork

Best Practices

โœ… Do This:

# Start private if there is any doubt.
# Private โ†’ public exposes the full history.                          // โœ…
# Use the CLI for repeatable creation.
gh repo create name --private --clone                                 // โœ…
# Add a README to initialize the repository.
# Without it, the repository is empty.                               // โœ…
# Use a .gitignore template.
# Prevents accidental commits of build artifacts.                    // โœ…

โŒ Don’t Do This:

# Don't create public if the repository may contain secrets.
# The history is exposed on visibility change.                       // โŒ
# Don't assume a new repository has a default branch.
# Empty repositories have no branch until the first push.            // โŒ
# Don't push to an empty repository without a local commit.
# The push fails with "src refspec does not match".                  // โŒ

Common Pitfalls

PitfallWhy It HappensFix
Push fails: “src refspec”Local repository has no commitsgit add and git commit first
Repository is empty after cloneCreated without starter filesExpected behavior; add files and push
Visibility cannot be changedOrganization restricted it to ownersContact the organization owner
Secrets exposed after visibility changeHistory contains the secretDelete the repository and recreate, or rewrite history
CLI clone fails--clone not passedRun git clone manually

Real-World Examples

1. Web UI Creation

+ โ†’ New repository โ†’ name, visibility, README โ†’ Create

2. CLI Private Clone

gh repo create my-project --private --clone

3. Empty Repository Connection

git remote add origin https://github.com/user/repo.git && git push -u origin main

4. Local-First Creation

git init && git add . && git commit -m "init" && gh repo create --source=. --push

5. Visibility Check

gh repo view user/repo --json visibility

6. Organization Repository

gh repo create my-org/repo --private

7. Clone Initialized Repository

git clone https://github.com/user/repo.git

8. Change Visibility

Settings โ†’ Danger Zone โ†’ Change visibility

9. README Initialization

Checked: creates README.md, repository has one commit

10. .gitignore Initialization

Checked: creates .gitignore for the selected language

Visual

The Creation Form

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  NEW REPOSITORY                                         โ”‚
โ”‚                                                         โ”‚
โ”‚  Owner:      [username โ–ผ]                               โ”‚
โ”‚  Name:       [my-project        ]                       โ”‚
โ”‚  Description:[optional          ]                       โ”‚
โ”‚                                                         โ”‚
โ”‚  Visibility: โ—‹ Public  โ— Private                        โ”‚
โ”‚                                                         โ”‚
โ”‚  Initialize:                                            โ”‚
โ”‚  โ˜‘ Add a README file                                    โ”‚
โ”‚  โ˜ Add .gitignore    [None โ–ผ]                          โ”‚
โ”‚  โ˜ Choose a license  [None โ–ผ]                          โ”‚
โ”‚                                                         โ”‚
โ”‚  [Create repository]                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Empty vs Initialized

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  WITHOUT STARTER FILES                                  โ”‚
โ”‚  Repository: no commits, no branches, no files          โ”‚
โ”‚  Clone: empty directory + warning                       โ”‚
โ”‚  Push: requires local commit first                      โ”‚
โ”‚                                                         โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”‚
โ”‚                                                         โ”‚
โ”‚  WITH README                                            โ”‚
โ”‚  Repository: one commit, default branch, README.md      โ”‚
โ”‚  Clone: directory with README.md                        โ”‚
โ”‚  Push: works immediately                                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Visibility Trap

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  PRIVATE REPOSITORY                                     โ”‚
โ”‚  Commit 1: adds config with API key                     โ”‚
โ”‚  Commit 2: removes the key                              โ”‚
โ”‚  History: both commits exist                            โ”‚
โ”‚         โ”‚                                               โ”‚
โ”‚         โ–ผ  visibility changed to public                 โ”‚
โ”‚  Anyone can clone and see Commit 1.                     โ”‚
โ”‚  The key is exposed.                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Local-First Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  git init my-project                                    โ”‚
โ”‚         โ”‚                                               โ”‚
โ”‚         โ–ผ                                               โ”‚
โ”‚  git add . && git commit -m "init"                      โ”‚
โ”‚         โ”‚                                               โ”‚
โ”‚         โ–ผ                                               โ”‚
โ”‚  gh repo create my-project --source=. --push            โ”‚
โ”‚         โ”‚                                               โ”‚
โ”‚         โ–ผ                                               โ”‚
โ”‚  Remote created on GitHub, local pushed                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Web UI URLhttps://github.com/new
CLI commandgh repo create
PublicVisible to anyone, forkable
PrivateOwner and collaborators only
Starter filesREADME, .gitignore, license
Empty repositoryNo commits, no branch
Visibility changePrivate โ†’ public exposes history
Organization restrictionOwners may restrict visibility changes

Key takeaways:

  • Visibility is the decision with consequences. A public repository is visible and forkable by anyone. A private repository is restricted. The choice is reversible, but private โ†’ public exposes the full history .
  • Starter files determine the initial state. A README creates a commit and a default branch. No starter files leaves the repository completely empty.
  • An empty repository cannot be pushed to without a local commit. The git push fails with “src refspec does not match any” if the local repository has no commits.
  • The CLI is the repeatable path. gh repo create name --private --clone creates the remote and clones it locally in one command.
  • The local-first flow is the alternative. Initialize the repository locally, commit, and use gh repo create --source=. --push to create the remote and push in one step.
  • Organization permissions may restrict visibility changes. The creator may not be able to change a public repository to private without the owner .

Remember: Creating a repository is a form with four decisions: name, owner, visibility, and starter files. The name determines the URL, the owner determines who controls it, the visibility determines who sees it, and the starter files determine whether the repository begins with a commit or with nothing. The visibility is the only decision that carries a lasting risk, and the risk is asymmetric: making a public repository private is safe from a secrecy perspective, but making a private repository public exposes everything that was ever committed. Start private if there is any doubt.


Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!