Git repository: how to create one with git init and add a remote
A Git repository is your project folder plus a hidden .git directory where Git stores the entire history of changes, branches and settings. You create one with git init inside the project folder or download an existing one with git clone. A remote repository is connected with git remote add origin followed by its URL.
A Git repository is a project whose changes are tracked by Git. Physically it's a regular folder with your files plus a hidden .git directory that holds the entire history: commits, branches, tags and settings. Delete .git and you're left with plain files and not a single past version.
What a repository is made of
When working with Git, it helps to keep in mind three areas that changes move between:
- working directory (working tree) — the files you see and edit;
- index (staging area) — a draft of the next commit, where changes land via
git add; - history — the commit database inside
.git, where changes land viagit commit.
Strictly speaking, the repository itself is the contents of .git. The working directory is just one "checked-out" version of the project that Git pulls out of the history.
How to create a Git repository with git init
Go to your project folder and run a single command:
cd ~/projects/my-app
git init
Initialized empty Git repository in /home/user/projects/my-app/.git/
You can create a repository in an empty folder or in one that already contains files. In the latter case nothing is lost: the existing files simply become untracked until you add them with git add.
Useful variations of the command:
# Create a folder and a repository in it in one go
git init my-app
# Set the name of the first branch (otherwise master or the configured default)
git init -b main
# Make main the default branch for all new repositories
git config --global init.defaultBranch main
Your first commit
An empty repository without commits is nearly useless. Right after git init you'd typically do this:
git config --global user.name "John Smith"
git config --global user.email "john@example.com"
git status
git add .
git commit -m "Initial project structure"
You only need to set your name and email once per machine — they're recorded in every commit. Without them Git refuses to commit and asks you to identify yourself.
Add a .gitignore right away
Before your first git add ., create a .gitignore file listing everything that must not end up in the repository: dependencies, builds, secrets, IDE files.
node_modules/
dist/
.env
.idea/
.vscode/
*.log
__pycache__/
If a file has already been committed, .gitignore won't remove it. You need to stop tracking the file while keeping it on disk: git rm --cached .env, and then commit.
What's inside the .git folder
You don't need to look in there during normal work, but understanding the structure answers a lot of questions:
| Item | What it stores |
|---|---|
objects/ | Compressed objects: file contents (blobs), directory structures (trees), commits |
refs/heads/ | Branches — files containing the hash of the latest commit |
refs/tags/ | Tags |
HEAD | Pointer to the current branch, e.g. ref: refs/heads/main |
config | Settings for this repository, including the list of remotes |
index | The state of the staging area |
hooks/ | Scripts triggered by events (pre-commit, pre-push) |
An important takeaway: a branch in Git is a tiny file with a single hash. That's why creating branches is instant and free.
How to check whether a folder is a Git repository
git status
# or, more precisely
git rev-parse --is-inside-work-tree
Outside a repository you'll get fatal: not a git repository (or any of the parent directories): .git. Note the "parent directories" part: Git searches for .git up the directory tree. If you accidentally run git init in your home directory, the whole thing becomes a repository — you'll need to delete that .git folder.
Local vs. remote repository
A repository created with git init exists only on your machine. To share code and have a backup, you connect a remote repository — a copy on a server: GitHub, GitLab, Bitbucket or your own Git server.
From Git's point of view, the remote isn't the "main" one: every copy is complete and contains the full history. It only becomes central by team convention.
git remote: connecting a remote repository
A remote is a short name for a server URL. By convention the primary one is called origin.
# Add a remote
git remote add origin git@github.com:username/my-app.git
# List remotes with their URLs
git remote -v
origin git@github.com:username/my-app.git (fetch)
origin git@github.com:username/my-app.git (push)
Then push your branch and link it to the remote one:
git push -u origin main
Essential git remote commands
| Command | What it does |
|---|---|
git remote -v | List remotes with their URLs |
git remote add <name> <url> | Connect a new remote repository |
git remote set-url origin <url> | Change the URL, e.g. from HTTPS to SSH |
git remote rename origin old | Rename a remote |
git remote remove old | Remove a remote (the server itself is untouched) |
git remote show origin | Details: branches, tracking, what's behind |
URL formats
https://github.com/user/repo.git— HTTPS, works everywhere, needs a token for writing;git@github.com:user/repo.git— SSH, needs a key, no password prompts once set up;/srv/git/repo.gitorfile:///srv/git/repo.git— a local path, handy for experiments.
Common errors
"error: remote origin already exists". A remote with that name already exists. If you need to change the URL, use git remote set-url origin <url> instead of running add again.
"failed to push some refs" / "Updates were rejected". The server has commits you don't — often a README created when the repository was set up on the website. Run git pull --rebase origin main and push again. If the histories are completely unrelated, Git will say "refusing to merge unrelated histories" — then git pull needs the --allow-unrelated-histories flag. It's easier to create the repository on the website empty.
"src refspec main does not match any". You're trying to push a branch that doesn't exist: either there are no commits yet, or the branch is called master. Check with git branch.
Your own Git server: a bare repository
GitHub isn't required. Any machine you have SSH access to can serve as a remote. On the server you create a bare repository — one without a working directory, only the contents of .git:
# On the server
ssh user@server
git init --bare /srv/git/my-app.git
# On your machine
git remote add origin user@server:/srv/git/my-app.git
git push -u origin main
For a team of three to work with such a server, it's enough to give your colleagues SSH access to the repository folder and a shared group with write permissions. For per-branch and per-project access control that's no longer enough — you'll need a full-fledged Git hosting solution.
You can't "go into" a bare repository and edit a file — it's meant only for exchanging changes via push and fetch. That's exactly how repositories on any Git hosting service work. If you need a web UI, code review and issues, people install self-hosted solutions such as GitLab, Gitea or Forgejo.
Remote-tracking branches: how your local repository sees the server
After you add a remote and run the first git fetch or git push, remote branches like origin/main appear in your repository. These aren't branches on the server, but local "snapshots" of what you saw on the server at the last sync. They're updated only by fetch, pull and push.
Hence the important difference between the three sync commands:
| Command | What it changes |
|---|---|
git fetch | Updates origin/*, leaves your branches and files alone |
git pull | fetch + merging origin/main into the current branch |
git push | Sends your commits and updates the branch on the server |
To see how far your branch is behind or ahead:
git fetch
git status -sb
## main...origin/main [ahead 2, behind 1]
Here you have two commits that aren't on the server, and the server has one that you don't. Before pushing, you need to pull that commit first.
The link between a local branch and a remote one (upstream) is set with the -u flag on the first push. If you forgot, you can set it separately: git branch --set-upstream-to=origin/main. To see all links, run git branch -vv.
Multiple repositories: monorepo or one per project
A common beginner question is how many Git repositories to create. A simple rule: one repository per unit that is developed and released independently. Study projects, pet projects and separate services are different repositories. Don't create one repository for your entire "My Projects" folder: the history gets mixed up, and publishing a single project to your portfolio becomes difficult.
Large companies sometimes keep all their code in a single monorepo for cross-cutting changes and a unified build, but that's a deliberate architectural decision with its own tooling. Beginners should start with the "one project, one repository" rule and never nest one repository inside another without submodules.
git init or git clone
| Situation | Command |
|---|---|
| Starting a new project from scratch | git init |
| You have a folder of code without version control | git init in that folder |
| The project is already on GitHub or a server | git clone <url> |
| You need a central repository on your own server | git init --bare |
After git clone the origin remote is already configured, so there's no need to add it manually.
Step by step: from a folder to a repository on GitHub
- Create a project folder and run
git init -b main. - Add a
.gitignoreand a README. - Make the first commit:
git add .andgit commit -m "Initial commit". - Create an empty repository on GitHub — no README, license or .gitignore.
- Connect it:
git remote add origin <url>. - Push your code:
git push -u origin main. - From then on, work in a loop: edit →
git add→git commit→git push.
Summary
A Git repository is your project plus a .git folder with the full history. You create it with git init, and connect it to a server with git remote add origin and the first git push -u. The remote can be GitHub, GitLab or your own Git server with a bare repository. Creating your first repository, the index and connecting a remote are covered hands-on in the Git course.
FAQ
How do I delete a Git repository but keep the files?
Delete the hidden .git folder in the project root: rm -rf .git on Linux and macOS. The files stay, but the entire version history is lost.
Can I run git init in a folder that already has a repository?
Yes, it's safe: Git reports Reinitialized existing Git repository and leaves the history alone. The command only recreates any missing internal files.
How many remotes can I add to one repository?
As many as you like. For example, origin for your fork and upstream for the original project — that's the usual setup for open source work.
Where are the settings for a specific repository stored?
In the .git/config file. Global user settings live in ~/.gitconfig and are set with git config --global.
How is a bare repository different from a regular one?
A bare repository has no working directory with files, only Git's internal data. It's used as a central repository on a server that people push to.
This topic is covered in depth with practice in the course “Git from Scratch to Confident Developer”.
- First Repository: init, add, commit, and the Magic of the Index
- GitHub and Remote Repositories: Your Code in the Cloud