The first GitLab screen can make a tiny project feel oddly official. There is a namespace to choose, a visibility decision, a README checkbox, and—waiting behind all of that—a terminal that may already contain months of work. The good news is that the setup is not fragile once you decide one thing first: does your code already have Git history?

This walkthrough follows an existing local folder into a new GitLab project, then shows the cleaner alternative when you are starting from nothing. The Git commands were exercised with Git 2.43.0 against a disposable local bare remote; GitLab interface, authentication, and branch-protection behavior were checked against current official documentation.

First, untangle the four names on the screen

  • Project: the GitLab workspace containing the repository, issues, merge requests, CI/CD settings, and members.

  • Repository: the Git object history and files inside that project.

  • Namespace: the user, group, or subgroup that owns the project and forms the URL path.

  • Project slug: the final URL component. “Weather CLI” might live at gitlab.com/acme-tools/weather-cli.

The README checkbox decides which road you are on

You already have a local project

Create a blank GitLab project and leave Initialize repository with a README cleared. GitLab then gives you an empty remote that can accept your existing history without inventing a competing first commit.

You are beginning a brand-new project

Select Initialize repository with a README, then clone the repository and work inside that clone. Your local copy begins with the same default-branch history as GitLab.

Create the empty GitLab home for existing code

  1. Select Create new → New project/repository → Create blank project.

  2. Choose a project name and inspect the generated slug.

  3. Select the correct personal or group namespace; it becomes part of the remote URL.

  4. Choose visibility according to who should read the source—not according to who may eventually use the deployed software.

  5. Leave Initialize repository with a README cleared for existing local history.

  6. Optionally enable security scanners available to your plan and instance, then create the project.

Pause before the first commit

weather-clibash
git --version
git status --short --branch
git version 2.43.0
## No commits yet on main
?? .env
?? .gitignore
?? README.md
?? src/

That uncomfortable .env line is a gift

  • git status --short --branch reports branch and concise file states without changing the working tree.

  • ?? means Git is not tracking the path; it does not mean the path is safe to commit.

  • Add secrets, generated output, dependencies, editor state, and local configuration to a project-appropriate .gitignore before staging.

  • If a secret was committed, removing the working-tree file is insufficient. Rotate the credential and use a reviewed history-cleaning procedure.

Turn the folder into a deliberate first commit

weather-clibash
git init -b main
git add README.md src/ .gitignore
git diff --cached --stat
git commit -m "Initial commit"
 README.md  | 12 ++++++++++++
 .gitignore |  3 +++
 src/main.py | 24 ++++++++++++++++++++++++
 3 files changed, 39 insertions(+)
[main (root-commit) a1b2c3d] Initial commit

A first commit should be boring in the best way

  • git init -b main creates a local repository and branch; it uploads nothing.

  • Explicit paths are easier to review than blindly staging the entire folder.

  • git diff --cached --stat summarizes the staged snapshot; git diff --cached shows its actual lines.

  • git commit records locally. The sample hash will differ on your machine.

  • If Git requests identity, configure suitable user.name and user.email; they identify commits and are not login credentials.

Connect the exact remote GitLab gives you

weather-clibash
git remote add origin git@gitlab.com:YOUR_NAMESPACE/weather-cli.git
git remote -v
origin  git@gitlab.com:YOUR_NAMESPACE/weather-cli.git (fetch)
origin  git@gitlab.com:YOUR_NAMESPACE/weather-cli.git (push)

Replace the placeholder; do not type around it

  • Copy the SSH or HTTPS URL from the project’s Code menu so host, namespace, and slug are exact.

  • origin is a conventional local nickname, not a GitLab requirement.

  • git remote -v verifies configuration only; it does not prove authentication or access.

  • For SSH, add and test a GitLab SSH key. For HTTPS with two-factor authentication, use a suitable personal access token.

Push once, then verify from both sides

weather-clibash
git push --set-upstream origin main
git status --short --branch
git branch -vv
To gitlab.com:YOUR_NAMESPACE/weather-cli.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.
## main...origin/main
* main a1b2c3d [origin/main] Initial commit

What success actually proves

  • --set-upstream (short form -u) links local main with origin/main for later push and pull defaults.

  • main...origin/main without ahead or behind counts means the local tracking references agree at that moment.

  • Open the GitLab repository page and confirm the expected files, branch, and commit message.

  • The output contains placeholders and a sample hash. The command sequence was validated locally; no live GitLab account operation is claimed.

If GitLab already has a README, begin by cloning

Terminalbash
git clone git@gitlab.com:YOUR_NAMESPACE/weather-cli.git
cd weather-cli
git status --short --branch
Cloning into 'weather-cli'...
## main...origin/main

Why cloning feels quieter

  • git clone creates a directory, copies reachable history, configures origin, and checks out the default branch.

  • Do not clone into a different non-empty project folder and expect Git to merge two projects automatically.

  • Add your source inside the clone, review it, commit it, and push through the shared history.

  • GitLab defaults to main only when project, group, and instance settings specify no other name. Trust the branch the clone checks out.

Give the project a safe first week

  • Describe it: document purpose, setup, tests, and ownership in the README.

  • Invite deliberately: use roles matching what each person must do; never share credentials.

  • Inspect branch rules: GitLab protects default branches by default, with details influenced by group and instance settings.

  • Prefer merge requests: push a feature branch, run CI, request review, and merge into the protected branch.

  • Add honest CI: a small pipeline running a real project check beats decorative green YAML.

  • Review secrets: enable suitable scanners, but treat them as a backstop rather than permission to commit credentials.

When the first push pushes back

  • `Permission denied (publickey)`: confirm the remote host, loaded SSH identity, GitLab account, and authentication test.

  • HTTP authentication failed: verify token scope and expiry; keep the token out of remote URLs, history, and files.

  • `remote origin already exists`: inspect it, then use git remote set-url origin <copied-url> if it is wrong.

  • Remote contains work: stop and inspect it. You may have initialized a README; do not overwrite history you have not reviewed.

  • Protected branch denied: push a feature branch and open a merge request, or ask a Maintainer about intended permissions.

  • `src refspec main does not match any`: confirm a commit exists and inspect git branch --show-current.

The moment it becomes a real project

It is not the moment GitLab draws a repository page. It is the quieter moment when you can make a change on a branch, see exactly what you are about to commit, push without fear, and explain who is allowed to merge it. Every later pipeline and merge request rests on that small sense of control.

References and next branches