learn-github-for-builders-with-phoebe / Session 2 of 6
Learn GitHub for Builders with Phoebe · Session 2 of 6 · Tech track

The daily loop: status, add, commit, push, pull

Session 1 gave you the model. This one gives you the rhythm - the five-command loop engineers run dozens of times a day without thinking. We wire your local repo to GitHub, keep secrets out of history with .gitignore, and build the one thing that separates confident builders from nervous ones: an undo toolbox you actually trust.

🟢 Foundation Builders & analysts Terminal or Codespaces 45 min live + self-study
0-3 · Welcome 3-18 · Concepts 18-40 · Build-along 40-45 · Q&A
Part 0

From one snapshot to a daily habit

Last session you made history by hand: init, add, commit, log. Today that becomes a loop you run all day, connected to a copy of your repo living on GitHub. The loop is only five commands, but the confidence comes from two things wrapped around it - keeping the wrong files out (.gitignore) and knowing exactly how to undo when something goes sideways. By the end you will push to GitHub, ignore a secret, and pick the safe undo tool for any "oh no" without guessing.

Live - presented in session Self-study - read after class ★ Build-along - type it in your terminal Running artifact: your my-project repo, now on GitHub
★ What you walk out with today The full loop as muscle memory (status → add → commit → push, pull before you push), your my-project repo connected to a GitHub origin, a .gitignore keeping a fake secret out of history, and a mental decision strip that maps every "undo this" to the one safe tool: restore, revert, or reset.
Part 1 · the rhythm

The loop: status, add, commit, push, pull 5 min live

Engineers do not think about these commands individually any more than you think about individual keystrokes when typing. They run one loop: check what changed, stage it, snapshot it, send it up, and pull teammates' work down. The new idea versus Session 1 is the remote - a copy of your repo that lives on GitHub, nicknamed origin. Push sends your commits up; pull brings other people's commits down.

One loop, run all day. Pull feeds in from GitHub before you push. edit status add commit push back to editing - the loop repeats origin (your repo on GitHub) pull: teammates' commits come down first
🔍 Click to zoom - the five-command loop, with pull bringing the remote down before push sends yours up
LiveWhy pull before push is the golden habit3 min▶
  • Local repo vs GitHub copy. Your commits are yours until you push. origin is the nickname for the GitHub copy - the shared source of truth your teammates also push to.
  • Push sends up, pull brings down. git push uploads your local commits to origin. git pull downloads commits others pushed and merges them into your branch.
  • Pull before you push. If a teammate pushed while you were working, pushing straight away gets rejected (your branch has diverged). Pulling first merges their work into yours so your push is a clean fast-forward. Make it reflex: pull, work, add, commit, pull again, push.
# the whole loop, once git status On branch main - modified: README.md # stage everything changed in this folder git add . # snapshot it with an imperative message git commit -m "Add usage section to README" # pull first (grab any teammate commits), then push yours up git pull git push To github.com:phoebefu6/my-project.git main -> main
Real world

A two-person data team both edit the same pipeline config on a Monday. The one who forgets to pull first gets "Updates were rejected because the remote contains work you do not have locally." The one who pulls first sees the teammate's change merge in cleanly and pushes in seconds. Same commands, one habit apart.

Self-studyFetch vs pull, and where origin comes from2 min read▶

git fetch downloads the remote's commits but does not merge them - it just updates your knowledge of what is on origin. git pull is fetch plus merge in one step. When you want to look before you leap, fetch and inspect; when you just want to sync, pull.

origin is set the first time you connect a repo to GitHub - either by gh repo create ... --source . or by git remote add origin <url>. See it any time with git remote -v. It is just a nickname; you can have several remotes, but origin is the conventional name for "the main one".

Part 2 · commit hygiene

.gitignore and commit hygiene 4 min live

Not everything belongs in history. Secrets, build junk, and giant dependency folders should never be committed - and .gitignore is how you tell git to pretend they are not there. The stakes are real: once a secret is committed, it lives in history forever, even if you delete the file later. Prevention beats cleanup every time.

# .gitignore - one pattern per line, put it at the repo root # secrets: never commit these .env .env.local *.key # dependency + build junk: regenerable, huge, noisy node_modules/ __pycache__/ dist/ # OS and editor cruft .DS_Store .vscode/
LiveIgnore the junk, write messages future-you can grep3 min▶
  • .gitignore keeps history clean and safe. Patterns match files git should never stage: secrets (.env), dependencies (node_modules/), build output (dist/), OS cruft (.DS_Store). GitHub's gitignore repo has a ready-made template for every language.
  • Good commit messages are imperative and explain why. "Add retry to the loader" beats "fixed stuff". The subject line finishes the sentence "If applied, this commit will...". Put the why in the body when it is not obvious - future-you debugging at 2am will thank you.
  • Conventional commits (optional but tidy). Prefixes like feat:, fix:, docs: make history skimmable and drive automatic changelogs (Session 6). Even solo, fix: handle empty CSV reads beautifully in git log.
  • Atomic commits. One logical change per commit. If your message needs the word "and", it is probably two commits. Atomic commits make revert and review surgical instead of scary.
Real world

The classic incident: a developer commits a .env holding live AWS keys, pushes to a public repo, and within minutes automated scanners find the keys and spin up crypto-mining bills in the thousands. Deleting the file in a later commit does not help - the keys are still sitting in history for anyone to git log. A single .env line in .gitignore prevents the whole story. .gitignore is a security control, not tidiness.

Self-studyAlready tracked? .gitignore will not save you2 min read▶

.gitignore only stops untracked files from being staged. If you already committed config.env, adding it to .gitignore does nothing - git is still tracking it. You have to stop tracking it explicitly:

# stop tracking a file but keep it on disk git rm --cached config.env git commit -m "Stop tracking config.env; add to .gitignore"

That removes it from future commits but it is still in past history. For a truly leaked secret, the only real fix is to rotate the secret (make the old one useless) and, if needed, rewrite history - which we flag as an advanced, careful operation. The lesson stands: ignore first, commit never.

Part 3 · the undo toolbox

The undo toolbox in safe tiers 6 min live

Three tools that people constantly confuse, sorted by how public the mistake is. The whole trick is matching the situation to the tool: have you committed yet? Have you pushed yet? Answer those two questions and the safe tool is obvious. The one rule that keeps you out of trouble: revert in public, reset only locally.

Ask two questions. The answer names the safe tool. Haven't committed? git restore Discards working-tree edits. Nothing was snapshotted yet. Committed and pushed? git revert New commit that undoes it. Safe - keeps shared history. Committed, local only? git reset Rewrites history - powerful. Never on a shared branch. The rule, in six words: revert in public, reset only locally. restore = pre-commit · revert = safe public undo · reset = local rewind only
🔍 Click to zoom - situation to tool: restore before commit, revert in public, reset only locally
LiveRestore, revert, reset - what each really does4 min▶
  • git restore - discard working-tree changes, before you commit. Edited a file and want the last committed version back? git restore <file>. Staged something by mistake? git restore --staged <file> unstages it. Nothing committed, nothing risky.
  • git revert - make a NEW commit that undoes a public commit. Safe because it never rewrites history: the bad commit stays, and a new one on top cancels it out. This is the only correct undo for anything you have already pushed and teammates may have pulled.
  • git reset - move the branch pointer, rewriting local history. Powerful and dangerous on shared branches. Three flavors: --soft keeps your changes staged, --mixed (default) keeps them unstaged, --hard throws the changes away entirely. Reset only commits that are still local and unpushed.
# restore: throw away an uncommitted edit to one file git restore README.md # revert: safely undo a commit that is already public git revert a3f901c [main 9ic2f0] Revert "Add broken parser" # the bad commit is still there; a new commit cancels it out - history intact
The one rule that keeps you safe Revert in public, reset only locally. If the commit has left your machine, revert it. If it is still local and unpushed, reset is fine. When unsure whether something was pushed, treat it as public and revert.
Self-studyThe safety net: reflog undoes almost anything2 min read▶

Terrified of reset --hard? Git keeps a private log of everywhere HEAD has been - the reflog - for about 90 days. Even after a hard reset that "deleted" commits, they are still reachable:

# every position HEAD has held, newest first git reflog 9ic2f0 HEAD@{0}: reset: moving to HEAD~2 a3f901c HEAD@{1}: commit: Add broken parser # bring the "lost" commit back by pointing a branch at it git reset --hard a3f901c

The reflog is why experienced engineers are calm about local mistakes: almost nothing is truly gone for 90 days. It is local-only, though - it will not recover work you never committed, which is why the habit is: commit early, commit often.

Build-along 1 of 3

Wire the loop to GitHub ★ 7 min · everyone connects

Open your my-project from Session 1 (or start fresh: mkdir my-project && cd my-project && git init). Confirm with git status.

Create an origin. Easiest: gh repo create my-project --public --source . --push. No gh? Make an empty repo on github.com, then git remote add origin <url> and git push -u origin main.

Edit the README (add a line), then run the full loop once: git status → git add . → git commit -m "Add project description" → git pull → git push.

Open the repo on github.com and confirm your commit is there. That round trip - local edit to visible on GitHub - is the loop you will run all week.

The -u flag, once per branch git push -u origin main the first time sets the upstream so that afterwards plain git push and git pull just work. You only need -u once per new branch.
Build-along 2 of 3

Add a .gitignore and stop a secret ★ 6 min · everyone types

Create a fake secret file: echo "AWS_KEY=totally-fake-12345" > .env. Run git status - git wants to track .env (it shows up as untracked). That is the danger.

Create a .gitignore containing one line, .env: echo ".env" > .gitignore. Run git status again - .env has vanished from the list. Git is now pretending it is not there.

Commit the .gitignore itself: git add .gitignore → git commit -m "Add .gitignore for secrets and junk" → git push. The .gitignore belongs in history; the .env never does.

Discuss: without that one line, the next git add . would have staged your keys and git push would have published them. Deleting .env later would not remove them from history. Prevention is the whole game.

Build-along 3 of 3

Pick the safe undo, every time ★ 8 min · everyone sorts

You have three undo tools and six "oh no" moments. Drag each situation to the tool that undoes it safely. Green means you matched the tier correctly - the same two-question logic from the decision strip.

Real world

On a shared main branch, an engineer who reflexively reaches for reset --hard to "clean up" a pushed commit rewrites history everyone else already has - and every teammate's next pull explodes with conflicts. The engineer who reaches for revert ships a clean undo commit that CI re-checks and everyone pulls painlessly. The habit you build here is the difference between a five-second fix and a team-wide mess.

After the session

This week ◐ 25 min total

Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · Why pull before you push?

When the remote has commits you do not, your branch has diverged and the push is rejected. Pulling first merges those commits into yours, so the push becomes a clean fast-forward.

2 · You committed a secret, then deleted the file in a later commit and pushed. Is the secret gone?

History is append-only by default. Deleting a file in a new commit leaves the old commit - and the secret - fully readable via git log. The real fix is to rotate the key so the leaked one is useless.

3 · A bad commit is on a shared branch everyone has pulled. Revert or reset?

Reset rewrites history, which breaks every teammate who already has the old commits. Revert is safe in public: the bad commit stays and a new commit cancels it out. Revert in public, reset only locally.

Source material

Official GitHub Skills coverage

This session completes the working content of GitHub's Introduction to Git exercise and adds the hygiene and undo skills every builder needs but the official course leaves thin.

✓Introduction to Git (skills/introduction-to-git)remotes, origin, push, pull - Part 1 + Build-along 1 complete the CLI working content started in Session 1
✓.gitignore as a security controlpatterns, secrets, the leaked-key incident - Part 2 + Build-along 2
✓The undo family: restore / revert / resetsafe tiers + the public/local rule - Part 3 + the sorter widget
◐reflog - the safety netself-study card; recovering after a hard reset
◐Conventional commits (feat:/fix:)mentioned in Part 2; drives automatic changelogs in Session 6

Session 2 cheat sheet · pin this

The loopstatus → add . → commit -m → pull → push. Run it all day.
Pull before pushGrab teammates' commits first so your push is a clean fast-forward, not a rejection.
First connectgh repo create --source . --push, or git remote add origin <url> + push -u origin main.
.gitignoreSecrets, node_modules/, build output, .DS_Store. A security control - a secret once committed lives in history forever.
Undo decision ruleNot committed → restore. Committed + pushed → revert. Committed, local only → reset. Revert in public, reset only locally.
Safety netgit reflog tracks every HEAD move for ~90 days - most local mistakes are recoverable.