---
title: 'Creating and Configuring a Repository'
source: 'https://academia.sh/en/courses/introduction-to-version-control/creating-and-configuring-a-repository'
course: 'Introduction to Version Control'
language: en
updated: '2026-08-17T18:10:47+00:00'
license: 'CC BY-SA 4.0'
---

# Creating and Configuring a Repository

Turning an empty directory into a repository, the contents of the `.git` directory, and the precedence of the system, user, and repository configuration layers.

The previous two lessons built the model: history is a directed acyclic graph, and in
a distributed system the whole of this graph stands locally. This lesson makes the
model concrete — the course's example repository, the `sozluk` project, is created,
and the repository's counterpart on disk is examined.

It is necessary to start with configuration, because a commit's author is read from
configuration, and the author information enters the commit's identity.

## Three Configuration Layers

Settings are kept in three separate files, and the narrower scope overrides the wider
one:

| Layer | Scope | Option |
|---|---|---|
| System | All users on the machine | `--system` |
| User | All of a user's repositories | `--global` |
| Repository | Only the repository currently in | `--local` |

If the same key is defined in more than one layer, the repository-level value takes
effect. This makes possible the distinction "I generally work under this identity,
but in this repository I use a different one."

Three settings are made at the user level:

```bash
git config --global user.name "Deniz Kaya"
git config --global user.email "deniz@ornek.test"
git config --global init.defaultBranch main
```

The first two fill in commits' author field; if either is undefined, an attempt to
write a commit stops with an error. The third sets the name of newly created
repositories' first branch. The **branch** concept is the subject of the Branching
and Collaboration course; here it will appear only as a name visible in output.

Where settings are written can be read:

```bash
git config --list --global
```

```
user.name=Deniz Kaya
user.email=deniz@ornek.test
init.defaultbranch=main
```

Notice that a key name's section and name parts are case-insensitive:
`init.defaultBranch` was written, `init.defaultbranch` was listed. Values, however,
are preserved letter for letter.

## Creating the Repository

A repository is set up inside an existing directory:

```bash
mkdir sozluk
cd sozluk
git init
```

The command writes a single-line confirmation: the phrase `Initialized empty Git
repository in` is followed by the full path of the created `.git` directory. Because
the path depends on the directory the command was run in, it differs on every
system.

From this moment on, the directory is a repository. The directory's visible content
has not changed; the only thing added is a hidden subdirectory named `.git`. The
repository is that subdirectory itself: if `.git` is deleted, the files remain,
history is gone.

## The Contents of the `.git` Directory

```bash
ls .git
```

```
HEAD
config
description
hooks
info
objects
refs
```

Four of the seven entries will be in constant use throughout this course:

- **`objects`** — the object database. The content-addressed storage covered in the
  previous lesson takes place here: file contents, directory images, and commits sit
  in this directory as files named by their hash values. It is empty in a new
  repository.
- **`refs`** — refs that bind human-readable names to object identities.
  `refs/heads` holds branch tips, `refs/tags` holds tags. Both are empty at the
  start.
- **`HEAD`** — a single-line file pointing to the ref currently being worked on.
- **`config`** — the repository's own configuration; the narrowest of the three
  layers.

The remaining three are used more rarely: `hooks` holds scripts to be run on certain
events, `info` holds repository-specific helper files, `description` holds a
description text that only some server interfaces read.

The `HEAD` file can be read directly:

```bash
cat .git/HEAD
```

```
ref: refs/heads/main
```

The content is not an object identity but a reference to a reference. Because no
commit has been written yet, the `refs/heads/main` file does not exist either;
`HEAD` points to a target that does not exist. This temporary inconsistency will be
resolved once the first commit is written.

## The Repository's Own Configuration

```bash
cat .git/config
```

```
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = true
```

These values are read from the system and written when the repository is created.
`repositoryformatversion` states the repository format's version, `bare` whether the
repository has a working directory, `logallrefupdates` whether ref changes are
logged. The last two depend on the file system: `ignorecase` is `true` on file
systems that do not distinguish case in file names (the usual configurations of
macOS and Windows); `precomposeunicode` is written only on macOS. Most Linux file
systems do not have these two lines.

To write a setting at the repository level, the command is run from inside the
repository, with the `--local` option:

```bash
git config --local user.email "deniz@baska-kurum.ornek"
```

This line affects only commits in the `sozluk` repository; the user-level value
stays in effect in other repositories.

## How the Repository's Root Is Found

Commands are not required to be run from the repository's root directory. When a
command runs, `.git` is searched for upward, starting from the directory currently
in; the first `.git` found determines the repository's root.

```bash
git rev-parse --show-toplevel
```

```
<parent-dir>/sozluk
```

The output is the repository's root directory's full path; above, the parent
directory's name has been abbreviated. Run from a subdirectory, it returns the same
value; where the root is does not change based on where you are. The relative path
between the root and where you are can also be asked for separately:

```bash
git rev-parse --show-prefix
```

```
temp/sub/
```

Because the search goes upward, running a second `git init` inside a repository does
not give the expected result: a new `.git` is created, and that subtree breaks off
from the outer repository. Separate mechanisms exist for cases that require nested
repositories; this course will use a single repository.

A command run outside a repository gives a clear error:

```
fatal: not a git repository (or any of the parent directories): .git
```

## Finding Where a Value Comes From

Which layer an unexpected setting comes from can be asked directly:

```bash
git config --list --show-origin --global
```

```
file:<home-dir>/.gitconfig	user.name=Deniz Kaya
file:<home-dir>/.gitconfig	user.email=deniz@ornek.test
file:<home-dir>/.gitconfig	init.defaultbranch=main
```

At the start of every line is the file the value was read from; in the output above
the home directory's path has been abbreviated, the real output shows the full path.
If the layer option is removed, all three layers are listed merged together, and it
is possible for the same key to appear on more than one line; in that case, the
**last** line is the one that takes effect.

A single key's effective value is asked for like this:

```bash
git config user.name
```

```
Deniz Kaya
```

## Initial Status

```bash
git status
```

```
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)
```

Three lines give three separate pieces of information. The first is the name of the
ref that the `HEAD` file points to. The second says that the `refs/heads/main` ref
has not yet been bound to an object. The third reports that nothing in the working
directory is ready to be recorded.

`git status` is the most frequently run command in this course. It answers the same
question every time: what differences exist between the working directory, the
staging area, and the last commit? The next topic will define these three regions
one by one.

## Summary

- Configuration is kept in system, user, and repository layers; a narrow scope
  overrides a wide one.
- If `user.name` and `user.email` are not defined, a commit cannot be written; these
  values enter the commit's identity.
- `git init` creates the `.git` subdirectory in an existing directory; the
  repository is that subdirectory.
- `.git/objects` holds the object database, `.git/refs` holds named refs,
  `.git/HEAD` holds the ref currently being worked on.
- `--show-origin` shows which file a setting comes from.

## Next Step

The repository is set up, but empty. What happens when a file is created — does it
go straight into history, or is there an intermediate stage? The next lesson will
define the staging area that stands between the working directory and the object
database, and show that area's counterpart inside `.git`.
