Git records versions of files on your computer. GitHub is the website where a team stores a shared copy and reviews proposed changes. This guide explains how one local change moves safely from your computer to that shared project.
Goal: work in the correct repository and branch, review one focused change, write a Conventional Commit, and open a draft pull request without merging it.
Prerequisites: complete Configure Git Identity And GitHub Access in your local Passport.
New to text commands? Read how to open a terminal and run one command before using a command block. It explains the labels used below and what to copy.
Execution context: run the commands on your own computer in Windows PowerShell, macOS zsh, or Linux Bash, from the repository folder named by the current step.
For your first practice change, follow the numbered Passport mission instead of copying selected commands from this reference.
Looking up one step? Read only the linked section, then return to your lesson. The clone and daily-work sections below are for a separate project, not extra tasks to complete before submitting your Passport exercise.
The Four Things To Identify First#
Before editing, identify:
| Item | Meaning | How to check |
|---|---|---|
| Repository | The project folder Git tracks | git rev-parse --show-toplevel |
| Branch | Your line of work | git branch --show-current |
| Working tree | Saved file changes not yet committed | git status --short |
| Remote | The GitHub repository used for pull and push | git remote -v |
A commit records a reviewed snapshot on your branch. A push sends your commits to GitHub. A pull request (PR) asks others to review a branch. These are separate actions.
1. Check The Tools#
Run one command at a time:
git --version
gh --version
Expected: each command prints a version. If one command is missing, return to the Passport setup page and install only that tool from its official source. Close and reopen the terminal before testing again.
2. Check The Active GitHub Account#
Inspect before changing anything:
gh auth status --active --hostname github.com
Expected: the output names the GitHub account that has access to the project. If no account is active, run:
gh auth login --hostname github.com --git-protocol https --web
If the correct account is already stored but another account is active, run:
gh auth switch --hostname github.com --user YOUR-GITHUB-USERNAME
gh auth status --active --hostname github.com
Replace the placeholder with your GitHub username. Do not put a token in a clone URL, Markdown file, chat, or terminal command.
3. Check The Commit Identity#
From the repository you are about to use, inspect the effective values and where they came from:
git config --show-origin --get user.name
git config --show-origin --get user.email
Keep correct, non-empty values. If either value is missing or wrong, set it in this repository only:
git config --local user.name "Your Real Name"
git config --local user.email "your-verified-github-email@example.org"
Use an email verified on your GitHub account or your GitHub no-reply address.
The email is commit metadata, not an ETH password or GitHub token. On a personal
computer where every repository must use the same identity, you may deliberately
replace --local with --global. Do not do that on a shared account or when
you use different GitHub identities.
4. Apply For GitHub Education If Eligible#
This step is for eligible students and does not block Git or GitHub practice. GitHub uses the Education benefits page for student verification and Student Developer Pack benefits.
- Keep using the same GitHub account verified in step 2.
- Open GitHub email settings.
- If your ETH email is absent, add it and complete the verification message.
- Open GitHub Education benefits.
- If GitHub already shows approved student benefits, keep them and stop here.
- Otherwise, submit the student application through GitHub's form.
- Continue the manual Git route while the application is pending.
GitHub Education is not required to clone a repository. It is used later for the optional no-cost GitHub Copilot Student route. Do not buy an AI product to complete the Git missions.
5. Clone A Private Project Once#
Obtain the exact repository identifier from the project owner in the form
OWNER/REPOSITORY, for example IDEALLab/example-project. Open that repository
on github.com with the account checked in step 2. If GitHub shows 404 or an
access error, stop and request access; cloning commands cannot bypass it.
Run the block for your operating system from the parent folder where you want the project folder to be created. It validates access and stops rather than overwriting an existing path.
Windows - PowerShell#
& {
$Repo = (Read-Host "Repository as OWNER/REPOSITORY").Trim()
if ($Repo -notmatch '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$') {
throw "STOP: enter exactly OWNER/REPOSITORY"
}
gh repo view $Repo --json nameWithOwner,defaultBranchRef
if ($LASTEXITCODE -ne 0) { throw "STOP: this GitHub account cannot read that repository" }
$Folder = ($Repo -split '/')[1]
if (Test-Path -LiteralPath $Folder) { throw "STOP: $Folder already exists; inspect it instead of cloning again" }
gh repo clone $Repo
if ($LASTEXITCODE -ne 0) { throw "STOP: clone failed" }
Set-Location -LiteralPath $Folder
git rev-parse --show-toplevel
}
macOS or Linux - zsh/Bash#
(
printf 'Repository as OWNER/REPOSITORY: '
read -r repo
printf '%s\n' "$repo" | grep -Eq '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$' || {
printf 'STOP: enter exactly OWNER/REPOSITORY\n' >&2
exit 1
}
gh repo view "$repo" --json nameWithOwner,defaultBranchRef || {
printf 'STOP: this GitHub account cannot read that repository\n' >&2
exit 1
}
folder="${repo#*/}"
[ ! -e "$folder" ] || {
printf 'STOP: %s already exists; inspect it instead of cloning again\n' "$folder" >&2
exit 1
}
gh repo clone "$repo" || exit 1
cd "$folder" || exit 1
git rev-parse --show-toplevel
)
Expected: the final line is the new project root. Clone once. If the folder
already exists, inspect it instead of creating project-2, project-final, or
another copy.
The Passport practice repository is prepared automatically. Do not clone it manually; use Prepare practice folder in the mission.
On macOS/Linux, the parentheses run the clone block in a temporary shell. Your terminal stays in the parent folder when it finishes. Enter the newly created project folder before step 6:
printf 'Folder name just created (the REPOSITORY part): '
read -r project_folder
if [ -d "$project_folder/.git" ]; then
cd -- "$project_folder" && git rev-parse --show-toplevel
else
printf 'STOP: this is not the new clone; check the folder name.\n' >&2
fi
Expected: the printed root matches the clone block's final line. Stop if it differs. This changes the current terminal's directory; a printed path alone does not.
6. Start From A Clean, Current Branch#
At the repository root, inspect before changing state:
git status --short --branch
git remote -v
Stop if you see changes you do not recognize or credentials embedded in a
remote URL. If the working tree is clean, run the block for your operating
system. It discovers the repository's default branch instead of assuming it is
named main, updates it only by fast-forward, validates your new branch name,
and refuses to reuse an existing branch.
Windows - PowerShell#
& {
if (git status --porcelain) { throw "STOP: working tree is not clean" }
$DefaultBranch = gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($DefaultBranch)) {
throw "STOP: could not identify the default branch"
}
$DefaultBranch = $DefaultBranch.Trim()
git fetch origin $DefaultBranch
if ($LASTEXITCODE -ne 0) { throw "STOP: fetch failed" }
git switch $DefaultBranch
if ($LASTEXITCODE -ne 0) { throw "STOP: could not switch to $DefaultBranch" }
git pull --ff-only origin $DefaultBranch
if ($LASTEXITCODE -ne 0) { throw "STOP: default branch did not fast-forward" }
$WorkBranch = (Read-Host "New branch name, for example docs/clarify-setup").Trim()
git check-ref-format --branch $WorkBranch | Out-Null
if ($LASTEXITCODE -ne 0) { throw "STOP: invalid branch name" }
git switch -c $WorkBranch
}
macOS or Linux - zsh/Bash#
(
[ -z "$(git status --porcelain)" ] || {
printf 'STOP: working tree is not clean\n' >&2
exit 1
}
default_branch="$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" || exit 1
[ -n "$default_branch" ] || { printf 'STOP: could not identify the default branch\n' >&2; exit 1; }
git fetch origin "$default_branch" || exit 1
git switch "$default_branch" || exit 1
git pull --ff-only origin "$default_branch" || exit 1
printf 'New branch name, for example docs/clarify-setup: '
read -r work_branch
git check-ref-format --branch "$work_branch" >/dev/null || {
printf 'STOP: invalid branch name\n' >&2
exit 1
}
git switch -c "$work_branch"
)
Expected: Git reports a newly created branch and git branch --show-current prints its name. Use the repository's naming rule if it has
one. Do not work directly on the default branch and do not use another person's
branch.
7. Edit One Focused Task#
Open the repository root in a plain-text code editor. Read the repository's
README.md, CONTRIBUTING.md, AGENTS.md, or equivalent instructions
before editing. Save only the files required for the task.
8. Review The Unstaged Change#
git status --short
git diff
Read every changed path and line. Remove accidental edits, generated files, credentials, data, and editor state before staging.
9. Stage Exact Files And Review Again#
Replace the example paths with files shown by your own git status:
git add -- src/module.py tests/test_module.py
git diff --cached --check
git diff --cached
The whitespace check is silent when it passes. The cached diff must contain only the intended change. Do not use Stage All for your first changes.
If an unintended file is staged, unstage that file without deleting it:
git restore --staged -- path/to/file
10. Create A Conventional Commit#
Semantic Versioning applies to release numbers such as 2.4.1. Conventional
Commits give commit messages a predictable format that release tools can use:
type(scope): short summary
Common types:
| Type | Use |
|---|---|
feat |
New user-facing behavior |
fix |
Bug fix |
docs |
Documentation only |
test |
Tests only |
refactor |
Code structure changed without intended behavior change |
chore |
Tooling or maintenance |
The optional scope names the main component, folder, or feature changed. Use
a short lowercase name such as parser, training, or onboarding. Omit
it when no honest scope is clear; do not use general merely to fill the
field.
Examples:
fix(parser): handle empty rows
feat(data): add tensile-test CSV loader
docs(onboarding): clarify NAS path check
test(training): cover an empty validation split
Run the repository's required tests, then commit only what you reviewed:
git commit -m "type(scope): short summary"
Do not claim tests you did not run. A breaking release change needs explicit
project-owner review; beginners should not invent ! or a BREAKING CHANGE
footer.
11. Push The Current Branch#
git push -u origin HEAD
HEAD means the branch currently checked out. Do not use --force to solve
a normal first push error.
12. Open One Draft Pull Request#
gh pr create --draft --fill
gh pr view --web
On GitHub, verify:
- the author is your account;
- the source is your feature branch;
- the target is the intended default branch;
- the commit subject is accurate;
- Files changed contains only the reviewed files;
- the PR is marked Draft.
Leave the Passport practice PR open. Do not merge it. If a PR already exists,
use gh pr status and update that branch instead of creating a duplicate.
Daily Loop After The First Mission#
git status --short --branch
git diff
git add -- path/to/reviewed-file
git diff --cached --check
git diff --cached
git commit -m "type(scope): short summary"
git push -u origin HEAD
Always inspect before changing state. Each collaborator uses a separate clone and branch. Share code through GitHub PRs, not through one writable Git checkout on NAS.
Using An AI Tool For A Commit Message#
Only after completing the manual Git and AI-agent missions, an agent may help summarize a diff. Give it this prompt:
Review only the staged diff. Propose one Conventional Commit subject in the
form type(scope): summary. Do not edit files, stage anything, commit, push, or
claim tests that are not visible in the supplied evidence. Explain the type and
scope in one sentence.
You remain responsible for checking that the message describes the actual staged change.
Common Failures And Safe Recovery#
- Private repository not found: verify the active account with
gh auth statusand confirm browser access. Do not paste a token into the URL. - Not a Git repository: run
pwdon macOS/Linux or(Get-Location).Pathin PowerShell, then enter the actual project folder. - Unexpected existing changes: stop and identify their owner. Do not reset or overwrite them.
- Commit includes the wrong file: if it has not been pushed, ask for help before rewriting history. If pushed, correct it with a new commit.
- Push rejected: fetch and inspect why histories differ. Do not force-push a shared or protected branch.
- Merge conflict: stop, read each conflict, and resolve with the other contributor when ownership is unclear.
- Secret committed: revoke or rotate it first, report privately, then follow the repository owner's history-cleanup procedure.
Verification#
- The active GitHub account has project access.
- The repository root, branch, and remote are correct.
- The staged diff and commit contain one focused task.
- Required tests actually ran.
- The PR is draft, reviewable, and not merged by the learner.
Ask For Help When#
You cannot identify existing changes, a branch has diverged, a secret may have been exposed, a protected branch rejects the workflow, or the repository's instructions conflict with this general guide. Share the error text only after removing credentials, personal information, private paths, and research data.
Primary Sources#
- GitHub CLI authentication
- GitHub: cloning a repository
- GitHub: creating a pull request
- Conventional Commits
- Semantic Versioning
Verified: 2026-09-04. Review by: 2026-12-04. Owner: lab software maintainer.