Lesson 03 / 15
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.
Contents
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:
git config --global user.name "Deniz Kaya" git config --global user.email "[email protected]" 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:
git config --list --global
user.name=Deniz Kaya [email protected] 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:
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
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/headsholds branch tips,refs/tagsholds 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:
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
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:
git config --local user.email "[email protected]"
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.
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:
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:
git config --list --show-origin --global
file:<home-dir>/.gitconfig user.name=Deniz Kaya file:<home-dir>/.gitconfig [email protected] 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:
git config user.name
Deniz Kaya
Initial Status
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.nameanduser.emailare not defined, a commit cannot be written; these values enter the commit’s identity. git initcreates the.gitsubdirectory in an existing directory; the repository is that subdirectory..git/objectsholds the object database,.git/refsholds named refs,.git/HEADholds the ref currently being worked on.--show-originshows 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.
To keep your progress and take notes, Log in
My notes
Log in to take notes.