Ana now has Git installed on her laptop, but before typing her first command she needs the vocabulary. Git has a lexicon of its own — dense and very precise: each word (repository, index, HEAD, branch, remote) names one specific thing, and using a term loosely is the front door to confusion. The words are also ordinary English pressed into narrow technical service, so it is easy to believe you understand a term when you only recognise it.
This lesson is a reasoned glossary. We are not going to run operations — that comes in module 2 — but to define what each term means and how it relates to the rest. The goal is that when module 3 tells you to "merge Bruno's branch into main", every word in that sentence has a sharp meaning in your head.
Contents
- Git's three areas
- The three states of a file
- The essential glossary
- References: HEAD, branches and tags
- Collaboration: remotes, clones and forks
- Integration: merge and rebase
- Vocabulary and the commands behind it
- How all the terms fit together
- Git's three areas
All work with Git happens in three distinct places. Understanding that separation is 50 % of understanding Git.
graph LR
WD["Working tree<br/>(working directory)<br/>your actual files"]
IDX["Staging area<br/>(index)<br/>what will go into the next commit"]
REPO["Repository<br/>(.git)<br/>committed history"]
WD -->|git add| IDX
IDX -->|git commit| REPO
REPO -->|git checkout / switch| WD
The working tree
This is the folder you see in the file browser: for Ana, the task-manager folder with index.html, styles.css, app.js and README.md. They are ordinary files, which you can open and edit with any program. Git does not interfere with them.
It holds one single version of the project: the one you are editing right now.
The staging area (index)
This is an intermediate zone that accumulates whatever will make up the next commit. Physically it is a binary file inside .git called index — which is why this zone goes by staging area, index or cache interchangeably, three names for the same thing.
Its reason to exist is control. Without it, committing would mean "save everything I have touched". With it, Ana can have modified five files and decide that only three of them, or even only certain lines of one file, form a change that stands on its own. The result is clean commits, each with a single intention.
The repository (.git)
This is the hidden .git folder inside the project. It holds the entire history: every commit, every version of every file, all the branches and tags, the local configuration and the references to the remotes.
Two practical consequences:
- Copy the project folder with its
.gitand you take the whole project along with its history. - Delete
.gitand the history disappears, leaving an ordinary folder of files. The current files survive; nothing else does.
| Area | Also called | Location | What it holds |
|---|---|---|---|
| Working tree | working directory | The project folder | One version of the files, editable |
| Staging area | index, cache | .git/index |
The draft of the next commit |
| Repository | object database | .git/objects |
The entire history, immutable |
- The three states of a file
As a corollary of the three areas, any file in a Git project is in one of these states.
stateDiagram-v2
[*] --> Untracked: new file
Untracked --> Staged: git add
Staged --> Committed: git commit
Committed --> Modified: you edit the file
Modified --> Staged: git add
Staged --> Modified: you edit it again
| State | Where it lives | Meaning |
|---|---|---|
| Untracked | Working tree only | Git can see the file but has never recorded it; it is not part of the project yet |
| Modified | Working tree | The file is already in the history and you have changed it, but the change is not marked for committing |
| Staged | Staging area | The change is marked to go into the next commit |
| Committed | Repository | The change is stored permanently in the repository |
An example with Ana's folder, still without running any commands:
- Ana creates
README.mdin a freshly created Git project → the file is untracked. - Ana stages it → it becomes staged.
- Ana commits → it becomes committed. It is now tracked and clean.
- Ana adds a line to
README.md→ it is modified again.
One file can be in two states at once: if Ana stages a change and then edits the file again, part of it is staged and part is modified but unstaged. This is bewildering at first and makes perfect sense once you see that the three areas hold independent versions.
- The essential glossary
This is the lesson's reference table. Come back to it whenever a term looks unfamiliar in later lessons.
| Term | Also called | Definition |
|---|---|---|
| Repository | repo | A project under Git's control: its files plus the .git folder with all its history |
| Working tree | working directory | The project files exactly as they sit on disk right now, editable |
| Staging area | index | The intermediate zone where the next commit is built |
| Commit | revision | A permanent snapshot of the project, with author, date, message and a reference to its parent |
| Hash / SHA | SHA-1, object ID | The unique 40-hexadecimal-character identifier Git computes from the content |
| HEAD | current position | A pointer to "where you are now": normally, the branch you are working on |
| Branch | line of development | An independent line of development; technically, a movable pointer to a commit |
| Tag | label | A fixed name given to one specific commit, typically a released version |
| Remote | upstream repository | Another repository, usually on a server, that you synchronise with |
| Clone | local copy | A complete copy of a repository, with all its history |
| Fork | server-side copy | A copy of someone else's repository under your own account on a hosting platform |
| Merge | integration | The operation that brings one branch's work into another, creating a merge commit |
| Rebase | replay | The operation that reapplies commits onto a different base, rewriting the history |
| Conflict | merge conflict | The situation where Git cannot combine two changes automatically |
| Tracked / untracked | known / unknown | Whether Git knows about that file or not |
| Ignored | excluded | A file Git deliberately skips, listed in .gitignore |
| Snapshot | tree state | The complete state of the project at a given moment |
| origin | default remote | The conventional name for the main remote |
| main / master | default branch | The branch that holds the project's official version |
| ref | reference | A readable name pointing at a commit (branches, tags and HEAD are all refs) |
The terms that take longest to sink in
Three of them deserve a paragraph of their own, because they cause the most confusion.
Commit. It is not "saving the file". It is recording a snapshot of the entire project at a specific moment, together with metadata: who made it, when, with what message and which earlier commit it starts from. It is identified by a hash such as a3f5c9e2b1d4..., shortened in practice to the first seven characters (a3f5c9e). Once created, it is immutable.
The word also works as a noun and a verb: you make a commit (create the snapshot) and you commit a change (record it). Both senses appear constantly, and which one is meant is almost always clear from the sentence — but the noun is the thing stored in .git, and the verb is the act of storing it.
Branch. Intuitively it is "a parallel line of development". Technically it is far simpler: a text file holding the hash of a commit. When Ana commits a change while on the main branch, Git updates that file so it points at the new commit. That is why creating a branch in Git is instant: it writes forty-one bytes to disk. Module 3 develops this in full.
HEAD. It is the answer to "where am I?". Normally HEAD points at a branch, and that branch points at a commit. When you switch branches, what changes is HEAD.
graph LR
HEAD["HEAD"] --> MAIN["main branch"]
MAIN --> C3["commit c3f8a21"]
C3 --> C2["commit 9d4e7b0"]
C2 --> C1["commit 1a2b3c4"]
There is a special case called detached HEAD: HEAD pointing straight at a commit instead of at a branch. It happens when you position yourself at a specific point in the history to inspect it. It is not an error, although the message Git prints is alarming the first time. Module 3 covers it.
- References: HEAD, branches and tags
All three are references (refs): readable names that point at commits. What separates them is their behaviour.
| Reference | Does it move? | What it is for |
|---|---|---|
| Branch | Yes, it advances automatically with each commit | Marking a line of development in progress |
| Tag | No, it is fixed | Marking a historic point: version 1.0, a delivery |
| HEAD | Yes, when you switch branches | Showing where you are working |
An example with task-manager, told as a story rather than as commands:
- Ana works on the
mainbranch. HEAD points atmain. - Bruno creates the
form-validationbranch to add validation to the form inindex.htmland works there. Bruno's branch moves forward;mainstays where it was. - When the application is released for the first time, the team puts the
v1.0tag on that commit. That tag will never move again: it will always point at exactly what was released.
Two kinds of tag
| Type | Full name | What it stores |
|---|---|---|
| Lightweight | lightweight tag | Just a name pointing at a commit |
| Annotated | annotated tag | An object of its own with author, date, message and an optional cryptographic signature |
Annotated tags are the recommendation for released versions, because they record who released what and when. Module 5 devotes a whole lesson to the subject.
- Collaboration: remotes, clones and forks
These three terms describe how one repository relates to others. Module 4 puts them to work; here we only define them.
Remote. A repository other than yours that you synchronise work with. It is not "the server": it is any other Git repository, which may live on GitHub, on a company server or even in another folder on your own disk. One repository can have several remotes, each with a short name. By convention, the main one is called origin.
Clone. A complete copy of a repository: all the history, all the branches, all the tags. When Bruno clones the task-manager repository, he will hold exactly the same information as Ana, and Git will automatically set up the origin remote pointing at the place he cloned from.
Fork. A platform concept, not a Git one. It is a copy of someone else's repository under your own account on GitHub, GitLab or similar, which lets you work on it without having write access to the original. It is the basis of the open source contribution flow, covered in module 7.
| Concept | Git's or the platform's? | Where the copy lives |
|---|---|---|
| Remote | Git | A reference to another repository, anywhere |
| Clone | Git | On your machine |
| Fork | The platform (GitHub, GitLab…) | In your account on the server |
The four verbs that will be in constant use from module 4 onwards:
| Verb | Command | What it does |
|---|---|---|
| Fetch | git fetch |
Downloads the remote's changes without touching your work |
| Pull | git pull |
Downloads the changes and tries to integrate them into your branch |
| Push | git push |
Uploads your commits to the remote |
| Clone | git clone |
Creates a complete local copy of a remote repository |
The distinction between fetch and pull is the one that trips up beginners most: fetch is always safe because it modifies nothing of yours; pull can trigger merges and conflicts.
- Integration: merge and rebase
Two ways of bringing two lines of development together. We only define them here; module 3 deals with merging and module 5 with rebasing.
Merge. Brings one branch's changes into another by creating a new commit — the merge commit — that has two parents: the last commit of each branch. The history keeps the real shape of what happened: two lines that diverged and came back together.
gitGraph
commit id: "HTML structure"
commit id: "base styles"
branch validation
commit id: "validate empty field"
commit id: "error message"
checkout main
commit id: "update README"
merge validation id: "merge"
Rebase. Takes a branch's commits and reapplies them one by one onto a different base, as though the work had been done from the most recent state all along. The result is a linear history with no visible fork. In exchange, the original commits are replaced by new ones with different hashes: it is a rewriting of the history.
gitGraph
commit id: "HTML structure"
commit id: "base styles"
commit id: "update README"
commit id: "validate empty field'"
commit id: "error message'"
| Aspect | Merge | Rebase |
|---|---|---|
| Shape of the history | Branched, reflects what happened | Linear, easier to read |
| The original commits | Kept intact | Replaced by fresh copies |
| An extra commit | Yes, the merge commit | No |
| Does it rewrite the history? | No | Yes |
| Risk of using it on shared branches | Low | High: it breaks everyone else's work |
Conflict. Both merging and rebasing can end in a conflict: it happens when the same lines of a file have been changed differently on the two sides, and Git cannot decide which is right. It is neither an error nor a failure: it is Git asking for a human decision. If Bruno and Carla modify the same rule in styles.css, there will be a conflict; if Bruno touches styles.css and Carla app.js, Git integrates both without intervention.
- Vocabulary and the commands behind it
Git's command names are terse and its vocabulary reuses everyday words with narrow meanings. This table closes the gap between the word you would say out loud and the command that performs it.
| Concept | Verb form | Related command (to recognise, not to use yet) |
|---|---|---|
| repository | to initialise | git init, git clone |
| working tree | to edit | git status |
| staging area | to index | git add |
| a staged change | to stage | git add |
| an unstaged change | to unstage | git restore --staged |
| a recorded change | to commit | git commit |
| commit | to make a commit | git log |
| commit message | to write a message | git commit -m |
| branch | to branch | git branch, git switch |
| the current branch | to switch / to check out | git switch |
| merge | to merge | git merge |
| merge conflict | to resolve | git merge |
| tag | to tag | git tag |
| remote | to add a remote | git remote |
| clone | to clone | git clone |
| remote changes | to fetch | git fetch |
| remote changes, integrated | to pull | git pull |
| your commits, published | to push | git push |
| history | to log | git log |
| differences | to diff | git diff |
| snapshot | — | — |
| an undone change | to revert | git revert |
| a moved pointer | to reset | git reset |
| shelved work | to stash | git stash |
| excluded files | to ignore | .gitignore |
| rewritten history | to rewrite history | git rebase |
A note on how people actually talk. In a real team you will hear all of these verbed, abbreviated and stretched: "I've committed it", "just cherry-pick it", "let's squash and merge", "open a PR", "your branch is behind". None of it is wrong in conversation. This course uses the precise term first and lets the shorthand appear afterwards, so that you recognise both.
- How all the terms fit together
To close, a mental map that puts every term in its place:
graph TD
R["REPOSITORY<br/>(project + .git)"]
R --> Z["Three areas"]
R --> O["Objects and history"]
R --> RF["References"]
R --> RM["Relationship with other repos"]
Z --> Z1["working tree"]
Z --> Z2["staging area"]
Z --> Z3["object database"]
O --> O1["commit"]
O --> O2["snapshot"]
O --> O3["hash / SHA"]
RF --> RF1["branch"]
RF --> RF2["tag"]
RF --> RF3["HEAD"]
RM --> RM1["remote"]
RM --> RM2["clone"]
RM --> RM3["fork"]
RM --> RM4["fetch / pull / push"]
And the sentence that sums up everything above, applied to our project:
In her
task-managerrepository, Ana edits files in her working tree, stages the changes she wants to group together in the staging area and creates a commit that is recorded in.gitfor good. HEAD tells her which branch she is working on; that branch advances with every commit. When they release a version, they add a tag. Bruno clones the repository from the remote calledorigin, works on a branch of his own and, when he is done, his work is merged with Ana's.
If that sentence reads clearly from end to end, the lesson has done its job.
Common Mistakes and Tips
- Confusing "saving the file" with "committing". Saving in the editor only writes to disk; Git knows nothing about it until you stage and commit. They are two unrelated operations.
- Treating the staging area as a nuisance. At first it looks like one bureaucratic step too many. It is exactly the opposite: it is what lets each commit carry a single intention instead of being a junk drawer. Its value becomes obvious the moment you have changes from three different tasks mixed together in your folder.
- Thinking a branch is a copy of the folder. It is not. It is a forty-one-byte pointer. This confusion, inherited from SVN, makes people avoid creating branches for fear of "duplicating the project".
- Using "fork" and "clone" as synonyms. Cloning brings a copy onto your machine (that's Git). Forking copies the repository into your account on the server (that's the platform). The usual sequence is to fork and then clone your fork.
- Reading "checkout" as "commit".
checkoutmeans "position yourself at", never "save". It is a dangerous false friend, because in some centralised systems it meant "lock a file for editing". - Reading a conflict as a failure. A conflict means Git has correctly spotted that two people changed the same thing and is asking you to decide. Seeing one is a sign that the system works.
- Tip: come back to this lesson. There is no need to memorise the table today. Keep it to hand and reread it at the start of each new module; the terms settle with use.
Exercises
Exercise 1: Identifying states
Ana has her task-manager repository with index.html, styles.css, app.js and README.md committed. Over an afternoon's work she does the following, in this order:
- Edits
styles.cssto change the background colour. - Stages
styles.css. - Creates a new file,
personal-notes.txt. - Edits
app.jsto add task deletion. - Edits
styles.cssagain to adjust a margin.
State which state each of the five files is in at the end of the afternoon. Watch out for step 5.
Exercise 2: Translating the jargon
Rewrite these five pieces of shop-floor jargon in precise terms using the lesson's terminology, and say which module of the course each operation belongs to:
- "Fork the repo and then clone it down."
- "Just stage the CSS, keep the JS out of the commit."
- "I pulled and got conflicts in
app.js." - "Tag 1.0 on master."
- "Rebase your branch onto main before you merge."
Exercise 3: Reasoned true or false
Say whether each statement is true or false and explain why:
- If I delete the
.gitfolder, I lose my project's files. - A tag moves automatically when I make a new commit.
git fetchcan cause a merge conflict.- A file can be staged and modified at the same time.
- A clone holds less information than the original repository.
- HEAD always points at a branch.
Solutions
Solution to Exercise 1
| File | Final state | Explanation |
|---|---|---|
index.html |
Committed, unchanged | It was never touched |
README.md |
Committed, unchanged | It was never touched |
styles.css |
Staged and modified at the same time | The colour change is staged (step 2); the margin adjustment (step 5) came later and is not staged |
personal-notes.txt |
Untracked | Git has never recorded it and it was not staged |
app.js |
Modified, not staged | It was edited but not staged |
The interesting case is styles.css: the version in the staging area (with the new colour, without the margin) and the one in the working tree (with both changes) are different. If Ana committed right now, the margin adjustment would not go into the commit.
Solution to Exercise 2
- "Make a copy of the repository in your own account (fork) and then clone it onto your machine." → Fork: module 7. Cloning: module 2 and module 4.
- "Stage only the CSS file; leave the JavaScript out of the commit." → Module 2.
- "I pulled the remote's changes and merge conflicts appeared in
app.js." → Pulling: module 4. Conflicts: module 3. - "Put a tag named
v1.0on the last commit of the main branch." → Module 5. - "Rebase your branch onto
mainbefore merging it." → Rebase: module 5. Merge: module 3.
Solution to Exercise 3
- False. The working tree files are ordinary files and they are still there. What you lose is the entire history: commits, branches, tags and local configuration. The project becomes an ordinary folder.
- False. That is a branch's behaviour, advancing with every commit. A tag is fixed by definition: it always points at the same commit. That is precisely what makes it useful for marking released versions.
- False.
fetchonly downloads information from the remote and updates the remote-tracking references; it touches neither your working tree nor your local branches, so it cannot cause conflicts. The one that can ispull, because it downloads and integrates. - True. It is exactly the case of
styles.cssin exercise 1. The three areas hold independent versions of the same file, so there can be differences between the repository and the staging area as well as between the staging area and the working tree. - False. A clone holds the complete history: every commit, branch and tag. That is precisely the defining feature of a distributed system, as we saw in the lesson What Is Git?. (Deliberately partial clones — shallow clones — do exist, but they are the exception rather than the rule; module 10 covers them.)
- False. HEAD usually points at a branch, but it can point straight at a commit: that is the detached HEAD state, which happens when you position yourself at a specific point in the history. Module 3 covers it.
Conclusion
You now have the vocabulary that holds up the rest of the course. The key concepts are three areas (working tree, staging area and repository) and three states (modified, staged, committed), which together explain the basic workflow. On top of them sit the references — branches, tags and HEAD — which are names pointing at commits, plus the collaboration concepts (remote, clone, fork) and the integration ones (merge, rebase, conflict), all developed in modules 3, 4 and 5.
You have also seen how each word maps to the command that carries it out, which matters because Git's command names are terse and its terminology reuses everyday words with very narrow meanings.
We now know what things are called. The next question is what they look like inside: what exactly Git stores when you commit, why the identifiers are forty-character hashes, and what lives inside .git. That is the content of The Git Data Model, the lesson that supplies the mental model every following module rests on.
Mastering Git: From Beginner to Advanced
Module 1: Introduction to Git
- What Is Git?
- Installing Git
- Basic Git Terminology
- The Git Data Model
- Configuring Git
- Initial Configuration
Module 2: Basic Git Operations
- Creating a Repository
- Cloning a Repository
- The Basic Git Workflow
- Staging and Committing Changes
- Inspecting Changes with git diff
- Viewing Commit History
Module 3: Branching and Merging
- Understanding Branches
- Creating and Switching Branches
- Merging Branches
- Merge Strategies
- Resolving Merge Conflicts
- Branch Management
Module 4: Working with Remote Repositories
- Understanding Remote Repositories
- Adding a Remote Repository
- Authenticating with Remote Repositories
- Fetching and Pulling Changes
- Pushing Changes
- Tracking Branches
Module 5: Advanced Git Operations
Module 6: Git Tools and Techniques
- Using Git Hooks
- Git Bisect
- Git Blame
- Git Log and Aliases
- Git Submodules
- Multiple Working Copies with git worktree
Module 7: Collaboration and Workflow Strategies
- Forks and Pull Requests
- Code Reviews with Git
- The Git Flow Workflow
- GitHub Flow
- Trunk Based Development
- Continuous Integration with Git
Module 8: Git Best Practices and Tips
- Writing Good Commit Messages
- Keeping a Clean History
- Ignoring Files with .gitignore
- File Attributes with .gitattributes
- Security Best Practices
- Performance Tips
Module 9: Troubleshooting and Debugging
- Common Git Problems
- Undoing Changes
- Resolving Divergence with the Remote
- Recovering Lost Commits
- Dealing with Corrupted Repositories
- Advanced Debugging Techniques
