Jan 8th, 2021 - written by Kimserey with .
In few of our previous posts, we referred to the HEAD, working tree and index when dealing with Git. In today’s post we will look at what those mean with example.
In Git HEAD is known as a reference or “refs”. References are stored under the /.git
folder and HEAD is under /,git/HEAD
.
For example if we display the content:
1
2
3
4
5
❯ cat .git/HEAD
ref: refs/heads/master
❯ cat .git/refs/heads/master
1911bf2d5227f92ba0b2f4bc03170e02e7a179fe
We can see that right now HEAD is a reference to another reference which itself a commit sha-1.
This second reference .git/refs/heads/master
is where our master
branch points to on our local repository. This allows us to reference master
instead of 1911bf2
. Similarly HEAD
can simply be referred as HEAD
with for example git show HEAD
.
Under /,git
we can also find ORIG_HEAD
which is the reference kept for safety when doing dangerous operations like git reset
allowing us to reset back to the original head.
So HEAD is simply a reference to the current commit we are working on. It usually points to the branch which itself is a reference to the latest commit on the branch. But HEAD can also sometime be a specific commit in cases of detached HEAD where we checkout a tag or a specific commit.
The working tree is the current tree on which we are working. It’s where our unstaged changes are kept. Git object model is built around files, trees, commits and references. A tree can be seen as directory which links files blob. We can see trees with ls-tree
, for example we show the tree from HEAD:
1
2
3
4
❯ git ls-tree HEAD
100644 blob 2ae827f56b06d064dd3e65e07e92c5a537aa99d3 .gitignore
100644 blob 42f11063a879b952f89165f7f4fa83ddca178408 HELLO
040000 tree 9d254d776ebe2b8e02e0269116f79976b1c5c306 _data
We see that HEAD is composed of blobs and trees and we can list the content of _data
which is a directory by using the hash.
Similarly we can look at the content of a file with cat-file -p
:
1
2
❯ git cat-file -p 42f11063a879b952f89165f7f4fa83ddca178408
Hello%
So the working tree is the current tree we are working on.
Commitish and treeish are words used in Git documentation to refer to an object pointing to a commit or a tree.
The index is a tree containing all files including staged changes. We can see its content with ls-files -s
:
1
❯ git ls-files -s
where -s
includes staged changes.
When doing a git diff
, we can use git diff --staged
to show the diff between the index and HEAD (which is usually a reference to the tip of the local branch checked out).
The index is the stage where all changes are prepared to be committed, once we do:
1
2
3
❯ git commit -am "Some changes"
[master 1328c74] Some changes
1 file changed, 2 deletions(-)
The changes from index are saved into a commit on our local master
, here at 1328c74
. From here our changes are inside our local repository and we can compare it to the upstream:
1
❯ git diff origin/master master
This would compare our local master
with origin/master
. Then we can push our local branch to the upstream wtih git push
to update origin/master
.
origin
is known as representing the remote repository. When we talk about remote, we are talking about the remote repository. We can list all our remote repository with:
5ab2f8a4323abafb10abb68657d9d39f1a775057
1
2
3
❯ git remote -v
origin https://....git (fetch)
origin https://....git (push)
We can see our origin
repository. Just like HEAD, origin
is also a reference:
1
2
3
4
5
❯ cat .git/refs/remotes/origin/HEAD
ref: refs/remotes/origin/master
❯ cat .git/refs/remotes/origin/master
e86ed6b7a9f8e3db7e58dc499728da479d2fac4a
The origin
remote is used to fetch (or pull) and push. When we clone a repository, the origin is set by default. If we create a new branch that isn’t track by the remote, we can use --set-upstream
or -u
to set the upstream branch to track the local branch. This is important to let us use git pull
and git push
without arguments.
So to summarize here is a graph showing the flow involved:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+--------------+ +-------+ +------------------+ +---------+
| | | | | | | |
| Working Tree | | Index | | Local Repository | | Remote |
| | | | | | | |
+------+-------+ +---+---+ +---------+--------+ +----+----+
| | | |
| | | |
| git add | | |
+--------------->+ | |
| | | |
| | git commit | |
| +---------------->+ |
| | | |
| | | git push |
| | +---------------->+
| | | |
In today’s post we looked at the definition of HEAD, working tree, index and remote in Git. Those terms are important terms to understand the Git documentation as they are used throughout the explanations. I hope you liked this post and I see you on the next one!