---
title: 'Committing Changes'
source: 'https://academia.sh/en/courses/introduction-to-version-control/committing-changes'
course: 'Introduction to Version Control'
language: en
updated: '2026-08-17T18:10:47+00:00'
license: 'CC BY-SA 4.0'
---

# Committing Changes

The staging area turning into a permanent record; the content of tree and commit objects, the four object types, the role of refs, and the atomic-commit habit.

The staging area has two entries, but history is still empty. This lesson turns those
two entries into a permanent record and opens up, one by one, the objects created in
the process. At the end, it discusses why a commit should hold "a single piece of
work."

## The First Commit

```bash
git commit -m "Terim listesini ve biçim belgesini ekle"
```

```
[main (root-commit) 13d31bf] Terim listesini ve biçim belgesini ekle
 2 files changed, 12 insertions(+)
 create mode 100644 README.md
 create mode 100644 terimler.txt
```

The `root-commit` in square brackets reports that this commit has no parent — that it
is the source of the graph. `13d31bf` is the shortened form of the commit ID. Because
the ID is computed from the author, the time, the message, and the content, you will
see a different value in your own repository; this holds for every ID shown throughout
the course.

```bash
git status
```

```
On branch main
nothing to commit, working tree clean
```

All three regions now show the same content: the working directory, the staging
area, and the last commit line up.

## Inside the Commit Object

A commit is a piece of text stored in the object database, and it can be read
directly:

```bash
git cat-file -p HEAD
```

```
tree 378e434005c6c42021d4398a15e89149b0fd8671
author Deniz Kaya <deniz@ornek.test> 1709532720 +0300
committer Deniz Kaya <deniz@ornek.test> 1709532720 +0300

Terim listesini ve biçim belgesini ekle
```

There are four components:

- **`tree`** — the ID of the tree object holding the project's exact snapshot at that
  moment.
- **`author`** and **`committer`** — the person who wrote and the person who recorded
  the change, followed by a Unix timestamp and a time zone offset. Why the two fields
  are separate will be seen in the third topic.
- **The text after the blank line** — the commit message.

Every commit other than the root commit also has a `parent` line. Since the parent
commit's ID is part of the text, it also enters the ID computation: changing a past
commit changes the ID of every commit after it.

## The Tree Object

```bash
git ls-tree HEAD
```

```
100644 blob 49daf9067744c72d7f5427d163f983c326ff37b5	README.md
100644 blob 9b9ef7052d54292add1ed75823a454c1fe66e3bb	terimler.txt
```

The **tree object** holds a directory's content: every line has a mode, an entry
type, an object ID, and a name. If the entry type is `blob`, it is a file; if `tree`,
a subdirectory. Subdirectories link to their own tree objects; the project directory
thereby turns into a tree structure whose root is the tree the commit points to. In
the terms of the Data Structures course: internal nodes are tree objects, leaves are
blobs.

Notice that the blob IDs are the same as their values in the staging area. `git
commit` did not write new blobs; it turned the staging area's entries into a tree
object and created a commit object pointing at that tree.

```bash
find .git/objects -type f
```

```
.git/objects/13/d31bf17fdc8a5292b7fff288de94088d5c1440
.git/objects/37/8e434005c6c42021d4398a15e89149b0fd8671
.git/objects/49/daf9067744c72d7f5427d163f983c326ff37b5
.git/objects/9b/9ef7052d54292add1ed75823a454c1fe66e3bb
```

Four objects: two blobs, one tree, one commit.

## The Four Object Types

| Type | What it holds | What it links to |
|---|---|---|
| blob | File content | — |
| tree | A directory's entries | Blobs and subtrees |
| commit | A snapshot and its metadata | A tree and parent commits |
| tag | A named pointer and its note | Usually a commit |

All four are stored the same way: a type-and-length header, followed by the content,
with the ID being the hash of that whole. The fourth type is covered in the course's
last lesson.

## Refs

A commit ID being a forty-character hash does not mean a person has to hold that
value in their head. Refs fill this gap:

```bash
cat .git/refs/heads/main
```

```
13d31bf17fdc8a5292b7fff288de94088d5c1440
```

The `refs/heads/main` file holds a single line: a commit ID. The previous lesson
showed that the `HEAD` file points to this ref. The chain is: `HEAD` →
`refs/heads/main` → commit → tree → blobs.

```bash
git rev-parse HEAD
```

```
13d31bf17fdc8a5292b7fff288de94088d5c1440
```

`git rev-parse` is the command that turns a name into an object ID. Names such as
`HEAD`, `HEAD~1` (the previous commit), and `main` are all resolved this way.

## Atomic Commits

A search script is added to the example project: `ara.sh`.

```sh
#!/bin/sh
# terimler.txt içinde arama yapar.

if [ $# -ne 1 ]; then
    echo "kullanım: ara.sh ARANAN" >&2
    exit 1
fi

grep -- "$1" terimler.txt
```

While writing the script, a typo is noticed in the format example inside
`README.md`, and the line `turkce | english` is corrected to `türkçe | english`. The
working directory now has two unrelated changes:

```bash
git status --short
```

```
 M README.md
?? ara.sh
```

Recording these two together in a single commit leaves a blurry entry in history,
something like "new script and a typo fix." An **atomic commit** is the smallest
consistent set of changes that serves a single purpose. Its criterion is this: when
the commit is undone, what remains should be consistent, and undoing it should not
take away more than intended.

The staging area is what makes this separation possible:

```bash
git add ara.sh
git commit -m "Terim arama betiği ekle"
```

```
[main 546c174] Terim arama betiği ekle
 1 file changed, 9 insertions(+)
 create mode 100755 ara.sh
```

The `create mode 100755` line shows that the file was recorded with execute
permission; the permission information is held in the tree object and is part of
history.

The second change is recorded separately. Changes in tracked files can be committed
directly, without staging, using the `-a` option:

```bash
git commit -a -m "Biçim örneğindeki yazımı düzelt"
```

```
[main 3132c78] Biçim örneğindeki yazımı düzelt
 1 file changed, 1 insertion(+), 1 deletion(-)
```

The `-a` option covers only tracked files; an untracked file does not enter a commit
this way. Its convenience comes at the cost of disabling the selection authority the
staging area provides — for this reason, it should not be used when more than one
concern is touched.

## Unchanged Content Is Not Rewritten

```bash
git ls-tree HEAD
```

```
100644 blob c0a6e3d5d4d0a0d117519512a1fb771c8a60bfee	README.md
100755 blob 4bc98c87b25ceac31de2e48015e81a943d2e73c8	ara.sh
100644 blob 9b9ef7052d54292add1ed75823a454c1fe66e3bb	terimler.txt
```

The `terimler.txt` blob is identical to its value in the first commit: `9b9ef70`.
Because the file has not changed across three commits, a single object is shared by
three trees. This is the answer to the snapshot model's objection of "does every
record rewrite all the files": since the same content produces the same ID, there is
nothing left to write a second time.

## Summary

- `git commit` turns the staging area's entries into a tree object and writes a
  commit object pointing at that tree.
- A commit object contains a tree ID, author and committer information, a message,
  and (except for the root commit) parent IDs.
- A tree object holds a directory's entries; subdirectories link to their own tree
  objects.
- There are four object types: blob, tree, commit, tag. All are named by the hash of
  content with a type-and-length header.
- An atomic commit is the smallest set of changes that leaves a consistent state
  when undone; the staging area makes this split possible.

## Next Step

Three commits have been written, and all three have a one-line message. The reason
for a fix, the options tried and abandoned, or the grounds for a decision do not fit
on one line. The next lesson takes up the commit message's structure — subject line,
body, and rationale — and the rules that make this structure keep history readable.
