Lesson 4 · Foundations
Create your course repository, then distinguish clone and open
Create GitTree Features from GitTree's New Tab screen and verify that it has no commits yet. Then make a separate local clone to see why opening a folder, initializing history and copying a repository are different actions.
- Level: Beginner
- 14 min read
- 6 min video
- Updated
- Before this lesson: Install Git and preview a safe commit identity, Predict what your next commit will contain
Progress saved in this browser.
Playing loads the video from YouTube (privacy-enhanced mode).
What you will learn
- Initialize the first course repository inside GitTree with an explicit branch name.
- Recognize an unborn branch without inventing a first commit.
- Save the fictional identity only in the course repository.
- Clone the same empty repository into a separate folder and check its origin.
- Reopen the original without creating or copying another repository.
Before you start
Begin where lessons 2 and 3 end: Git is available, and no course repository exists. Lesson 2 previewed GitTree Demo; it did not save global config. You need an existing, writable parent folder reserved for course work. The child gittree-features must be new or empty, outside existing source checkouts. Do not initialize inside this web repository or a personal project.
Use Git meeting the inspected GitTree minimum 2.39.0. The commands and screens in the video were recorded with Git 2.52.0 and GitTree 2.0 on Ubuntu 24.04, in a private home folder, and the checks in this article ran against the repositories that recording created. They were not run on macOS or Windows. Default shortcuts use Command on macOS and Ctrl on Windows and Linux; the native folder chooser looks different on every system and was not filmed.
Once you are signed in to GitTree, these local workflows need no provider integration, Pro or trial: the Free plan covers them. The clone uses a file:// URL on the same machine, not hosted GitLab or Claude credentials.
Concept
Init creates Git repository metadata for a chosen directory. It does not create a commit merely because a branch name is present. A new ordinary repository has a working-tree directory and an initially empty index. HEAD can symbolically name refs/heads/main before that branch has any commit to point at: an unborn branch.
Clone creates a different repository from a source. Ordinarily it copies accessible history and checks out the selected source branch, while recording a remote called origin. Here the source is deliberately empty, so there is no history or working content to copy. That is a valid edge case, not a failed upload.
Open selects an existing repository for inspection in GitTree. Opening a tab is not cloning its files, creating a commit or adding a hosting service. The app can update its recents/workspace state and perform trust checks separately.
The three verbs are like creating a new notebook, making a separate copy, and placing an existing notebook on your desk. Do not extend the analogy into permissions: a repository's settings or hooks can execute programs, so GitTree reviews their trust rather than treating “open” as unconditional execution permission.
| Action in this lesson | Working tree/index | Local refs | Remote refs/config |
|---|---|---|---|
| Initialize original with main | New ordinary worktree; no project files or indexed entries | Symbolic HEAD names unborn main; no commit tip | No remote configured |
| Save local demo identity | No file/index/history content changes | No ref changes | Writes only user.name/user.email in original repository config |
| Clone original into a separate folder | New empty worktree/index in the copy | Still no commits | Copy has origin pointing to original; no remote-tracking branch tip exists yet |
| Reopen original | Selects the existing original; no duplication | No commit/ref creation | Original remains without a remote |
A bare repository is history storage without ordinary working files. It is useful in later server exercises, but it is the wrong choice for building this landing page. Optional .gitignore/licence templates would create uncommitted files; decline them to preserve this checkpoint.
For native semantics, see git-init and git-clone. The app's empty/new-destination checks are stricter than native Git's ability to reinitialize an existing repository. Do not use the terminal to evade an app refusal without understanding what it protected.
In GitTree — the canonical first initialization
The actual current-source labels are New Tab card Init, dialog Initialize a repository, submit Initialize. “Init a repository” in the older plan was descriptive, not the current button text.
- Choose New Tab (
tab.new), Command+T / Ctrl+T. Expect the Open, Clone and Init cards. - Click Init. Expect Initialize a repository, with no changes saved before submission. Alternative: Command Palette… with Command+Shift+P / Ctrl+Shift+P → Initialize Repository… (
repo.init). No direct default shortcut is asserted for Init. - In Location, type the full path to your new
gittree-featuresdirectory under the reserved existing parent. You can use Browse…, then the native chooser Choose where to create the repository; native OS chooser buttons are not invented here. Recheck the final full Location after browsing. - Set Initial branch to
main. Keep Bare repository (history only, no working files) off. - Set .gitignore template and Licence to None when those template controls are loaded. Their defaults are no selection; if the controls are absent, do not silently add files elsewhere. Keep Open after creating on.
- Review Location, main, bare off, templates None and open-after on. Choose Initialize once. Expect the repository to be created and opened, possibly through the normal trust workflow. Do not press repeatedly while pending.
- If Trust this repository? appears, review its actual path and findings. Cancel leaves it unopened; Open in Restricted Mode limits operations; Trust and Open permits normal repository settings/hooks. For this self-created sandbox, choose Trust and Open only after the findings are understood. In the recording, no trust prompt appeared for the new folder; do not expect every fresh repository to show this dialog.
- Confirm the tab is the original
gittree-features, not the parent or a similarly named copy. Its graph has no commit yet. Do not create an initial “cleanup” commit to remove the empty state.
Save the repository-local fictional identity
- With the original active, open Preferences (
app.preferences.open), Command+, / Ctrl+,. - In the repository-specific navigation section, choose gittree-features. That is the dynamic repository name, not a global Profiles page. At narrow widths its page-picker label is Repo-Specific: gittree-features.
- Find Name for commits (setting
repo.userName, backing Git keyuser.name). Under its Writes to, select or verify Local (this repository). Do not choose Global (every repository). - Enter
GitTree Demoand choose the row's Apply. Alternatively, press Enter in that field. Wait for Saved before continuing. - For Email for commits (
repo.userEmail, backinguser.email), verify the same Local target, enterdemo@example.com, then Apply or Enter. Wait for Saved. - Choose Exit Preferences. Expect the original repository still active and its history still empty. The local config changed, not the working files or graph.
Typing alone leaves a draft. Escape in a dirty field cancels that draft first; it is not a guaranteed “leave everything” shortcut. The explicit Apply/local target is why this step differs from lesson 2's cancelled preview.
In the terminal — verify the app result
Replace <course-parent> with your own reserved absolute parent path, keeping quotes around paths. Run these after app initialization, not in the web checkout:
cd "<course-parent>/gittree-features"
git rev-parse --is-inside-work-tree
git rev-parse --is-bare-repository
git symbolic-ref --short HEADObserved query results, in order:
true
false
mainProve that no commit exists:
git rev-parse --verify --quiet HEADObserved: no stdout or stderr; exit status 1. That is the expected unborn-branch result, not a corruption diagnosis. Symbolic HEAD and revision verification answer different questions.
Inspect files, index and remote names:
git status --short
git ls-files
git remoteEach command produced no output and exited 0 in the fixture. These queries alone do not prove that every ignored file is absent. In your file manager, inspect the reserved folder with hidden items visible: it should contain repository metadata .git, but no project files yet. Do not edit anything inside .git.
Read only the two explicit local identity fields:
git config --local --get user.name
git config --local --get user.emailObserved:
GitTree Demo
demo@example.comNo personal/global config dump is needed.
Native initialization alternative — not a second canonical start
The native equivalent for a separate disposable comparison copy, or someone studying Git without the app, is:
cd "<course-parent>"
git init --quiet --initial-branch=main --template= gittree-featuresIt printed no output and exited 0 in the isolated fixture. Do not rerun it on the original already created in GitTree. The empty native template option controls Git's template directory; it is not the app's optional .gitignore/licence selector. On a normal machine, inherited templates/settings must still be reviewed.
If setting identity by the native path instead of the app row, select the new repository first and deliberately write only local config:
cd "<course-parent>/gittree-features"
git config --local user.name "GitTree Demo"
git config --local user.email demo@example.comBoth writes were silent successful operations in the isolated verification copy. They are alternatives to the app writes, not an excuse to skip verifying the app take.
Clone a separate local copy
This small side exercise uses the same project, not a second demo application. The original stays the course checkpoint and must be active again before lesson 5. It is not a remote added to the original.
In GitTree
- Open New Tab, then Clone. Alternative palette: Clone Repository… (
repo.clone). Expect Clone a repository. - Choose Clone with URL. In Repository URL, enter the original's absolute local URL, for example
file:///absolute/course-parent/gittree-features, replacing that example with your actual reserved path. The app's URL parser accepts absolute file URLs; a raw local path is not its supported input. Use a simple sandbox path without spaces for this first exercise; URL encoding and Windows drive syntax need their own platform recheck. - In Parent folder, choose the same existing course parent. In Folder name, explicitly enter
gittree-features-copy. Check Clones into points to the copy, not the original. - Leave Depth empty for full history; keep Also clone submodules, Sparse checkout: only the top-level files at first, then the folders you choose and Download file contents only when they are needed (blobless) off. Keep Open after cloning on.
- Choose Clone once. Expect actual clone progress or a rapid completion for this empty local source, then the copy opens through any required trust review. Do not insist that every progress phase is visible for such a small operation.
- Inspect the copy's empty graph and use the terminal checks below. Its
originbelongs to the copy, pointing to the original. A configured origin is not an existing remote-tracking branch or a hosted provider. - To return, choose Open from New Tab or Open Repository… (
repo.open), Command+O / Ctrl+O, select the originalgittree-featuresfolder and review any required trust prompt. The recording instead used the Open button on the original's row in Recent on New Tab, which opened it the same way; the system chooser was not filmed. Alternatively, drop that original folder onto New Tab's folder-drop surface (not filmed). Expect the original selected/open; do not promise whether the current build reuses a tab or creates another. - Keep the supplemental copy untouched. You do not need to delete it to continue. Confirm the original still has no remote and the local demo identity before lesson 5.
Native comparison and result
From the reserved parent, in a separate take where the destination does not exist:
git clone --quiet "file://<absolute-source-path>" gittree-features-copyHere <absolute-source-path> starts with / on the macOS recording, making a URL with three slashes after file:. Replace the placeholder; do not type the angle brackets. The exact observed stderr, despite a successful exit 0:
warning: You appear to have cloned an empty repository.Now query the copy:
cd "<course-parent>/gittree-features-copy"
git remote
git symbolic-ref --short HEAD
git config --local --get user.nameFirst two observed outputs:
origin
mainThe last query prints nothing and exits 1: cloning did not copy the original's local user.name configuration. An external global setting may still supply an effective identity on your real machine; the local query deliberately answers only what this clone contains. Do not read all global config on camera. We do not commit inside the copy.
Result
At the end of this lesson, the original is an ordinary repository with symbolic unborn main, no commit, no project files, an empty logical index, no remote, and local identity GitTree Demo / demo@example.com. The optional supplemental clone has origin but no history; it is outside the continuing project checkpoint.
The graph remains empty by design. Lesson 5 creates README.md and index.html and makes the first deliberate commit.
Common mistakes
- Choosing the parent instead of the new child: verify Location and the active tab before any config write.
- Choosing bare mode: a bare repository does not provide the landing page's ordinary working files.
- Adding templates: they introduce untracked files that do not belong to this empty checkpoint.
- Treating unborn HEAD as corrupt: symbolic main without a commit is normal immediately after init.
- Cloning onto the original: destination must be a separate new/empty folder.
- Assuming clone copies local identity: it copies repository history, not the original's local user.name/user.email.
- Continuing in the copy: its origin makes its state different from the canonical original.
If something goes wrong
A nonempty destination refusal means GitTree protected an existing folder. Choose a new empty child; do not delete its contents to silence the error. “The folder that should contain it does not exist” means you must create/select the reserved parent deliberately before retrying.
If a repository already exists, open it and inspect it; do not reinitialize it to make the course appear fresh. If it is unrelated work, leave it unchanged and choose a separate course folder.
If clone fails, read the actual error and cleanup result. GitTree distinguishes a removed clone-owned folder, a preserved pre-existing folder, unexpected extra content and cleanup failure. Cancel Clone requests cancellation; it is not evidence that every byte vanished. Inspect retained content before removing anything. The empty-source warning alone is not failure.
If trust findings are unfamiliar, choose Cancel or restricted mode. Do not blanket-trust an arbitrary repository to get through a lesson. Restricted mode disables network operations and may limit working-tree actions.
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
Reopen the original through Open Repository… or folder drop. Run the three state queries, verify missing HEAD commit, empty status/index/remote queries and the two local identity values. Explain why main is visible without a commit and why the supplemental copy, if created, has origin but the original does not.
Changed-input prediction: if a separate new initialization uses Initial branch = trunk, predict git symbolic-ref --short HEAD. It prints trunk; it still creates no commit. This was checked in another isolated native fixture. Do not rename the continuing course's main branch to perform the prediction.
Your own confirmation: the site cannot see your computer.
To complete the lesson, answer the required questions correctly and confirm the practical exercise.
Recap
- Init creates repository metadata; clone creates a separate copy; open selects existing data.
- A new main can be unborn: no first commit is implied.
- Keep local identity and supplemental-clone state separate from global settings and the canonical project.
Related
Glossary terms introduced
Initialize — تهيئة; clone — استنساخ; repository — مستودع; branch — فرع; remote — بعيد; working tree — مجلد العمل; staging area — منطقة التجهيز. “Unborn branch” means a branch name without a first commit; HEAD and origin remain literal identifiers.
Video transcript
The narration of the video, cue by cue.
Show the transcript
- Create the course repository, then separate cloning from opening.
- Use a reserved parent folder outside existing source repositories.
- Initialize new history, clone a separate repository, or open an existing one.
- Start inside GitTree on the New Tab screen.
- Choose Init. Review the dialog before creating anything.
- Enter the full path to the new gittree-features folder.
- The native folder chooser is an alternative; recheck the final location.
- Choose main explicitly instead of relying on a machine default.
- Keep bare mode off because this project needs working files.
- Decline both optional templates to preserve the empty checkpoint.
- Keep Open after creating enabled, then review every choice.
- Initialize once and wait for the actual repository result.
- If trust review appears, read the findings before granting trust.
- The original exists, but its first commit does not.
- HEAD can name main before main has a commit to point at.
- Open this repository's Preferences page, not the global Profiles page.
- Check the write target before typing the fictional identity.
- Apply GitTree Demo as this repository's commit name.
- Apply the fictional email at the same local scope.
- Enter can apply a field too. Exit only after both writes succeed.
- Check that you are inside the original working tree.
- The bare-repository check must be false.
- The symbolic branch check should print main.
- No commit resolves yet. Silent exit one is expected here.
- These three inspections should produce no output.
- Read only the two local identity values, not private global settings.
- Native Git can initialize too, but do not reinitialize the app-created original.
- Now copy this same empty repository into a separate local folder.
- Open Clone and use the URL path rather than a provider account list.
- Use an absolute file URL for the original, not a raw local path.
- Name the destination explicitly and confirm it is not the original.
- Keep the full-history defaults and leave advanced clone options off.
- Run the clone and let the actual progress finish.
- An empty source produces a copy without commits; that can still succeed.
- The empty-repository warning is not a failure by itself.
- The copy has origin and an unborn main, not a hosted pipeline.
- Cloning did not copy the original's local commit-name setting.
- Origin belongs to the copy. The original did not gain a remote.
- Open the original again before continuing the course.
- Dropping the existing folder is another way to open it, not clone it.
- Check the original again: no remote, no commit, and the local demo identity.
- A separate initialization with trunk reports trunk, still without a commit.
- A destination refusal protects existing content. Choose a new folder.
- If a clone fails or is cancelled, read what cleanup actually retained.
- Undo and reflog are not promised rollback for initialization or identity settings.
- Init creates metadata, clone creates a copy, and open selects existing data.
- Verify the original's state before adding the first files.
- Next, create the hero and make the first deliberate commit.