Lesson 5 · Foundations
Stage the intended snapshot and make your first commit
Create the project's README and hero page inside GitTree, select what belongs in the first commit, and deliberately leave a later edit uncommitted. Prove what was recorded instead of judging success by a notification alone.
- Level: Beginner
- 15 min read
- 7 min video
- Updated
- Before this lesson: Predict what your next commit will contain, Create your course repository, then distinguish clone and open
Progress saved in this browser.
Playing loads the video from YouTube (privacy-enhanced mode).
What you will learn
- Create and save the first two project files in GitTree.
- Stage and unstage without confusing either operation with deleting a working file.
- Compare the index with the working tree before committing.
- Write a useful summary and commit only the prepared snapshot.
- Verify the first commit's files, identity and remaining working change.
Before you start
Start where lesson 4 ends. The original gittree-features is an ordinary repository on unborn main, with no commits, project files or remotes. Its local identity is GitTree Demo / demo@example.com. Do not continue inside lesson 4's supplemental gittree-features-copy.
GitTree's inspected minimum is Git 2.39.0. The video was recorded with Git 2.52.0 and GitTree 2.0 on Ubuntu 24.04: the two files, their staging and the first commit were made in the app itself, and the terminal checks ran against what the app created or against separate copies of the project in states A, B and C, so the original was never replayed. Nothing was run on macOS or Windows, and Ubuntu is the only Linux system recorded; Command-key and Windows chords come from the keymap source.
Native Git needs no account for a local commit. In GitTree, sign in and the Free plan covers this lesson. No provider, Pro/trial, AI drafting, API key, CI runner or cloud environment is required. Do not add a remote to make a local commit.
Concept: select contents, then record them
A commit is not “save everything visible.” In this lesson a normal commit records the index: the complete selected snapshot. It creates a root commit and makes main point to it. It does not push anywhere.
Saving in the editor updates the working tree. Staging updates the index from the chosen working file. Unstaging changes the index selection; it is not Discard and does not remove the working file in our exercise. Before the first commit there is no earlier committed version to restore, so an unstaged new file becomes untracked again.
A prepared edition is a useful analogy: you can revise your working draft after preparing an edition, then publish the prepared edition locally without including the newer draft. Staging is not a live subscription to subsequent edits. Git's add reference documents that selection; the commit reference distinguishes ordinary index commits from other modes.
We use no -a, explicit commit path arguments, amend, empty commit or automatic stage-all. The index is a whole next-tree description, not just a list of changed names.
| State | Working index.html | Index index.html | HEAD/main | Remote |
|---|---|---|---|---|
| A: saved initial files | HTML-01 | Absent | Unborn | None |
| B: both files staged | HTML-01 | HTML-01 | Unborn | None |
| C: supporting line edited after staging | HTML-01-WORKING | HTML-01 | Unborn | None |
| D: ordinary commit succeeds | HTML-01-WORKING | HTML-01 | First commit contains HTML-01 | None |
README-01 is also staged and committed. After D, README is clean; index.html intentionally remains modified only in the working tree. The graph can have a new commit while status is not clean.
Complete project files
Use UTF-8, LF and one final newline. Do not include Markdown fences in the saved files. There is no package.json, CSS, JS or runnable Node suite yet; those arrive in lesson 6.
README.md — README-01
# GitTree Features
A fictional landing page used to learn Git and GitTree.
All people and addresses in this repository are fictional.
No form submits information to a server.index.html — HTML-01, before staging
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Understand every change.</h1>
<p id="hero-copy">A clear view of Git history.</p>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn.</p></footer>
</body>
</html>index.html — HTML-01-WORKING, only after staging
Replace the saved working file with this full body after the earlier version has entered the index:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Understand every change.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn.</p></footer>
</body>
</html>The single intended replacement is the hero-copy supporting line. Do not change the main heading or any other bytes.
In GitTree
1. Create and save the two initial files
- Confirm the original repository's name and main context. Open Command Palette…, Command+Shift+P / Ctrl+Shift+P, type New File… and select that exact command (
files.newFile). With no folder argument, it starts at the project root. - In New File, set Path from the project folder to
README.md, then choose Create. Expect the new working file to open in the file workspace. Creation refuses an existing path rather than overwriting it. - Focus the editable content area, paste the complete README-01 body, then choose Save. Alternative: Command+S / Ctrl+S while the working editor has focus. Expect the Unsaved changes indicator to clear after actual save success.
- Repeat New File… → path
index.html→ Create. Paste the complete HTML-01, not the later working variant. Save and wait for the unsaved indicator to clear. - Choose Back to Graph in the file toolbar, or the palette command Back to Graph (
view.returnToGraph). Then use the palette Show Working Changes (wip.show). Expect README.md and index.html under Unstaged Files, with nothing under Staged Files. - Notice Stage Changes to Commit if it is the primary composer button while nothing is staged. Its source-defined action stages all working changes; it does not already mean a successful commit. We use deliberate per-file staging instead.
Saving an editor buffer is not staging. Seeing a file in a tab is not proof that its latest buffer reached disk.
2. Stage, unstage safely, then prepare both files
- For README.md under Unstaged Files, use its Stage File row action. Keyboard alternative: select only that row, keep focus in the unstaged list and press S; the palette command is Stage (
wip.stageSelected). Expect README.md under Staged Files. - For that README row under Staged Files, choose Unstage File. Keyboard alternative: select only it, keep focus in the staged list and press U; palette command Unstage (
wip.unstageSelected). Expect README.md to return to Unstaged Files. Its working contents remain intact. - Stage README.md again, then stage index.html with its Stage File action. Expect exactly two staged file paths.
- Click each staged row to inspect its complete addition. index.html must still contain A clear view of Git history. Do not infer contents from a file count alone.
The single-letter shortcuts are scoped to their lists, not a request to type S/U into an editor or summary. No drag-and-drop staging behavior is assumed.
3. Save a later edit without staging it
- Open Show Files (
files.focus), Command+Shift+E / Ctrl+Shift+E. Focusindex.htmlin the Files tree and press Enter to open its working copy. Alternative: click its existing saved working-file tab. Work in the editable File view, not a historical blob or a staged diff. - Replace its entire content with HTML-01-WORKING above. Save via Save or Command/Ctrl+S. Wait for actual disk save success.
- Return through Back to Graph, then Show Working Changes. index.html now appears in both lists. Click its Unstaged Files row: the diff shows the later supporting-line replacement.
- Click its Staged Files row: the first-commit addition still contains the earlier supporting line. Do not choose Stage File for that newer working edit or Stage All Changes now. That would change the commit you are preparing.
4. Write the message and commit the index
- In the composer Summary field (placeholder Commit summary), enter exactly
feat: add the GitTree Features hero. Leave Description empty. This summary says what changed; it does not promise a finished site or a passing test suite. - Keep Amend Previous Commit off. Expand Commit Options and verify Skip Hooks (--no-verify), Add Signed-off-by, Different Author, Push After Commit and Allow Empty Commit are all off. Do not add co-authors or invoke AI drafting.
- Review the two staged paths and the earlier prepared hero line one last time. Choose Commit Changes to 2 Files. Keyboard alternative: Command+Enter / Ctrl+Enter, routed through palette command Commit (
commit.submit), only after confirming the active repository and pending state. - Wait for Git's actual result. A successful result references a measured SHA; do not copy a fabricated SHA from a diagram. Expect a first graph commit on main. In this unchanged-submission case the message draft clears after success.
- Inspect the post-commit lists: nothing remains staged; index.html remains under Unstaged Files with the later line. Do not click Stage Changes to Commit to “finish” this intentional result.
The displayed file count is two staged paths, not three rows across two lists. Push After Commit is a separate follow-up choice; it is off and there is no remote.
In the terminal
Run in <course-parent>/gittree-features, replacing the placeholder with your reserved actual parent. If you already performed an app mutation, inspect its resulting state; do not replay the equivalent mutation and accidentally advance beyond the checkpoint.
Saved files, before staging
git status --shortObserved:
?? README.md
?? index.htmlIntentionally trying a normal commit with no staged content:
git commit --quiet -m "feat: add the GitTree Features hero"Observed stdout with exit 1, no stderr:
On branch main
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
index.html
nothing added to commit but untracked files present (use "git add" to track)No commit was created. This negative case explains why selecting files matters; do not use an empty commit to bypass it.
Native stage/unstage equivalents
In a separate replay of the same saved-file state:
git add -- README.md
git rm --cached --quiet -- README.mdBoth commands were silent successful. --cached is essential: it removes the new entry from the index, not the working file. The checked README bytes remained unchanged and short status again showed the two untracked files. This is specifically an uncommitted new-file example; do not generalize it to deleting tracked project files.
Prepare both:
git add -- README.md index.html
git status --short
git diff --cached --statObserved status:
A README.md
A index.htmlObserved summary:
README.md | 6 ++++++
index.html | 21 +++++++++++++++++++++
2 files changed, 27 insertions(+)The stat summary counts lines, not correctness. Review actual staged content before committing.
After saving the later working edit
git status --short
git diff -- index.htmlObserved status:
A README.md
AM index.htmlObserved working diff:
diff --git a/index.html b/index.html
index 5470374..27f8718 100644
--- a/index.html
+++ b/index.html
@@ -13,7 +13,7 @@
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Understand every change.</h1>
- <p id="hero-copy">A clear view of Git history.</p>
+ <p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn.</p></footer>Those are measured file-blob abbreviations from the exact LF contents, not fictional commit SHAs. Short-status spacing and abbreviation length can vary with formatting configuration; the two comparisons must stay the same.
Read the exact prepared file:
git show :index.htmlFull observed output:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Understand every change.</h1>
<p id="hero-copy">A clear view of Git history.</p>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn.</p></footer>
</body>
</html>Commit and verify
In the native replay only, without re-staging the later edit:
git commit --quiet -m "feat: add the GitTree Features hero"Observed: no output, exit 0. This fixture had no active hooks/signing and only the fictional local identity. Do not disable a real project's hooks/signing to force a tutorial success.
Inspect either the native or actual app result:
git log -1 --format="%s%n%an <%ae>%n%cn <%ce>"
git rev-list --count HEAD
git ls-tree --name-only HEAD
git status --short
git diff --cached
git remoteObserved outputs in order for the first four commands:
feat: add the GitTree Features hero
GitTree Demo <demo@example.com>
GitTree Demo <demo@example.com>
1
README.md
index.html
M index.htmlThe last two commands each produced no output and exited 0. The working edit remains; no remote exists. This is a local first commit, not an upload.
For independent content confirmation, git show HEAD:index.html returned the full HTML-01 body displayed above as the prepared output; git diff -- index.html still showed the exact supporting-line replacement. The index matched HEAD for both paths. The newer file was not lost.
Result
At the end of this lesson, main points to exactly one commit with the declared summary and fictional author/committer. HEAD and index contain README-01 and HTML-01; working index.html contains HTML-01-WORKING. Status has a leading space then M for index.html. There is no remote.
Do not “clean” the intentional edit, make a second commit, amend the root or add the optional practice notebook before handing this checkpoint to lesson 6. Any later clean-continuation notebook belongs in a separately preserved variant, not this two-file first commit.
Common mistakes
- Saving without staging: disk bytes and selected commit bytes differ.
- Staging again after the deliberate edit: valid Git behavior, but the newer line would enter the commit, changing this lesson's result.
- Counting all visible rows as staged files: one path can have staged and unstaged comparisons.
- Using Stage All Changes as a final cleanup: it would select the edit intentionally left out.
- Enabling amend or automatic push: those are different operations with different scope.
- Calling unstage Discard: unstage edits the index selection; Discard can remove working content.
If something goes wrong
If New File refuses an existing path, cancel and inspect it. Do not overwrite unknown content. If the editor reports that the disk changed, preserve both versions and use its Review Changes, Reload from Disk or Keep Editing controls according to the actual state; do not blindly select Overwrite with My Edits.
If the commit is blocked because nothing is staged, choose the intended files and review them. If identity is missing, inspect the local settings from lesson 4; a failed attempt can offer Set up your Git identity, with an explicit repository target. It does not justify a global identity write, and saving identity does not mean the commit automatically succeeded.
If Git refuses a commit or a hook fails, read Hook Output when available. The source-defined refusal text is The commit was not created. Your message and staged changes are unchanged. Correct the stated cause and recheck the index before retrying. Do not tick Skip Hooks merely to manufacture a green take. Recheck actual HEAD after uncertain outcomes before submitting again.
If a commit was created with unexpected contents, stop and record its real SHA, working/index state and message. Do not immediately amend, reset or click Discard. Changing the configuration now does not change metadata already stored in that commit.
Check your understanding
Answer each question, then read why. Questions marked “Required” count toward completing the lesson.
0 of 6 correct
Answer the required questions correctly to complete the lesson.
Checked in this browser.
Practice
Use the article's status/content queries on your completed original. Explain why exactly one commit and a remaining working modification are both correct. Record your prediction before reading the prepared file.
For a separate disposable replay only, stage the later edited index.html before committing. Predict that the newer line is recorded and status becomes clean. Do not change the original to perform this alternative. When no browser exercise exists yet, use the two transcripts and explain the different outcomes.
Your own confirmation: the site cannot see your computer.
To complete the lesson, answer the required questions correctly and confirm the practical exercise.
Recap
- Saving changes the working file; staging selects contents for the next ordinary commit.
- The first commit records the index and advances local main, without pushing.
- Verify contents, identity and leftover work separately; a dirty result can be intentional.
Related
Glossary terms introduced
Stage — تجهيز; unstage — إلغاء التجهيز; commit — إيداع; index — الفهرس; working tree — مجلد العمل; untracked — غير مُتتبَّع; author — المؤلف; committer — المُودِع. Discard means التخلّص من التغييرات and is not the same as unstage.
Video transcript
The narration of the video, cue by cue.
Show the transcript
- Create the hero, prepare one edition, and prove what your first commit saved.
- Start in the original repository from L004, not its supplemental clone.
- Saving, staging and committing change different snapshots.
- Create the first file through GitTree's New File command.
- Name it README dot em dee, at the project root.
- Save the complete fictional-project README, not the Markdown fences.
- Create index dot H T M L in the same repository.
- Save the original hero with this supporting line.
- Open working changes to see both new, untracked files.
- With nothing staged, this button stages all changes first.
- The terminal confirms two untracked files, not two commits.
- A normal commit cannot record these files before you select their contents.
- Stage only the README first.
- Unstage it again. Its saved working text stays intact.
- Unstage changes the selection; Discard can remove working content.
- Now stage both intended files, one by one.
- The S and U shortcuts work in their focused lists, not inside text fields.
- Review the staged content, not just the file count.
- The summary counts lines; it does not prove those lines are correct.
- The prepared edition is still the original hero.
- Reopen the working file, not the staged comparison.
- Save the later supporting line without staging it.
- The same path now appears in both comparisons.
- The unstaged comparison shows the later edit against the index.
- The staged addition still contains the earlier line.
- Read the index directly to prove what is prepared.
- Without staging again, which supporting line will the first commit contain?
- Write a summary that describes the hero you actually added.
- Keep amend and all optional behaviors off for this first local commit.
- Commit the two staged paths, not every visible row.
- Wait for Git to confirm creation before treating the operation as complete.
- Main now points to its first local commit.
- The later working edit remains outside the commit on purpose.
- Verify the subject, author and committer independently.
- There is one commit containing exactly these two paths.
- An empty cached diff can coexist with a working modification.
- The recorded file is earlier; the working file still has the newer line.
- Nothing was uploaded. This repository still has no remote.
- If you stage the later edit first, the prepared edition changes.
- That alternative commit records the newer line and leaves a clean result.
- The commit shortcut is an alternative submission, not a second finishing step.
- If Git refuses, inspect its output and the staged content before retrying.
- Do not discard the remaining edit or assume Undo covers every buffer.
- Your checkpoint is one exact commit plus one deliberate working edit.
- Check the recorded contents, identity and leftover work separately.
- Saving writes the working file; staging selects; committing records.
- Keep the later edit. Next, inspect diffs and add the project's tools.
- Continue from this verified state, not from a guessed clean folder.