Basic Tutorial for Git/GitHub for Beginners Part-2

In
Part 1 we stayed on your machine: git init, staging, committing, git log, and creating an extra branch. That is the muscle memory everything else builds on.
Part 2 is about talking to GitHub (or any remote), keeping your laptop and the server in sync, ignoring junk files, merging or rebasing branches, cherry-picking fixes, staging exactly what you mean—and knowing when a force push is acceptable (and when it is not).
Before you start #
You will need:
- A GitHub account (sign up here if you do not have one yet).
- The same Git repo you used in Part 1, or any small project folder with at least one commit.
- Comfort running commands in Terminal—we will stay there.
If git --version fails, revisit the install links from Part 1.
Put the repo on GitHub #
- On GitHub, click New repository. Pick a name (for example
SampleGit), keep it empty for this walkthrough—no README, no.gitignore, no license—so your existing history stays simple. - GitHub will show you commands; we will mirror that flow below.
On your machine, from inside your project folder:
git remote -v
Expect no output until you add a remote.
Add GitHub as origin (replace the URL with yours—HTTPS or SSH is fine):
git remote add origin https://github.com/YOUR_USERNAME/SampleGit.git
git remote -v
You should see fetch and push URLs listed.
main vs master #
New repos often use main as the default branch; older tutorials use master. Check what you have:
git branch
Whatever name is green is your current branch. When you push, use that name in the command below.
Publish it (first push):
git push -u origin main
If your branch is master, swap it:
git push -u origin master
The -u sets the upstream so later you can type git push without extra arguments.
Refresh GitHub in the browser—you should see dummy.txt (and your commits) online.
Bring changes down: git pull #
When the remote has new commits—maybe you edited files on the web UI, or pushed from another machine—update your local branch:
git pull
Behind the scenes Git fetches updates and then merges them into your current branch. For day-to-day solo work, git pull is enough; when collaboration gets noisy, it helps to learn git fetch first and inspect before merging.
Copy a repo from scratch: git clone #
Starting on a new computer is usually:
cd ~/Desktop
git clone https://github.com/YOUR_USERNAME/SampleGit.git
cd SampleGit
You now have the full history locally and origin already configured.
Switch branches (the modern way) #
You created a sample branch in Part 1. Jump onto it:
git switch sample
Older tutorials use git checkout sample—same idea for switching branches. ( checkout can do more than switch; for beginners, git switch keeps intent obvious.)
Go back to main (or master):
git switch main
Stage files with precision #
Part 1 showed git add on a single file and git add .. In real projects you often want finer control—especially when one file mixes two unrelated edits.
Stage specific paths
git add src/App.swift README.md
Stage updates to files Git already tracks (modified + deleted), but not brand-new untracked files:
git add -u
git add -u Documentation/
Interactive (“patch”) staging walks change hunks one by one so you can stage only part of a file:
git add -p
Press ? in the prompt if the letters (y, n, s split hunk, etc.) feel cryptic at first.
See what will go into the next commit
git diff # unstaged changes
git diff --staged # already staged (aka --cached)
Unstage without losing edits in your working tree (modern Git):
git restore --staged path/to/file
Older tutorials often show git reset HEAD path/to/file—same idea.
Merge branch work into main #
Say sample has commits you want on your primary branch:
git switch main
git merge sample
If Git can combine histories cleanly, it opens your editor for a merge commit message or completes a fast-forward. If two people edited the same lines, Git asks you to resolve conflicts—that is a separate post; for solo practice you rarely hit it early on.
git rebase: replay your work on top of another branch #
Merge keeps a fork in the graph: both histories stay visible. Rebase takes commits from your current branch and replays them on top of another tip—often origin/main—so the story reads linear.
Typical flow while you are on a feature branch:
git fetch origin
git switch my-feature
git rebase origin/main
If Git stops with conflicts: fix files, git add each resolved path, then git rebase --continue. To bail out completely: git rebase --abort.
Interactive rebase reshapes recent commits—squash noisy WIP commits, reword messages, reorder:
git rebase -i HEAD~3
Your editor opens a small script; the comments explain pick, squash, reword, etc.
Caution: rebasing changes commit hashes for everything replayed. Do not rewrite commits that already live on main unless your team agrees on the workflow. For shared branches, git revert and plain merges stay safer.
git cherry-pick: pluck a single commit #
Sometimes you want one fix from branch hotfix without merging the whole branch:
git log --oneline hotfix # copy the hash you need
git switch main
git cherry-pick abc1234
Git applies that commit’s patch on top of main. If conflicts appear: resolve, git add, git cherry-pick --continue, or git cherry-pick --abort to unwind.
.gitignore: stop committing noise #
Some files should never enter Git: Xcode DerivedData, node_modules, secrets, local .env, macOS .DS_Store, build folders.
Create a file named .gitignore at the root of the repo:
.DS_Store
*.log
.env
Use community templates when you adopt real stacks—for example github/gitignore.
After saving:
git add .gitignore
git commit -m "Add gitignore for local junk"
git push
Undo work without rewriting history (mostly): git revert #
Suppose a commit on main introduced a bug but you still want history to stay honest for teammates:
git log --oneline -n 3
git revert COMMIT_HASH
Git creates a new commit that undoes the chosen one. Safe for branches people already pulled.
git reset: powerful, sharp, private branches only #
git reset moves HEAD (and optionally your staging area / working tree). It can erase commits from your local branch’s timeline—fine on a branch nobody else has pulled, risky on main after push.
Common variants:
git reset --soft HEAD~1— Drop the last commit but keep changes staged.git reset --mixed HEAD~1(default) — Drop the last commit; changes stay as unstaged edits.git reset --hard HEAD~1— Drop the commit and delete those changes from disk. Destructive.
Until you are confident, prefer git revert on shared branches.
git push --force and --force-with-lease #
After git rebase, git reset, or cherry-pick workflows that rewrite commits you already pushed, a normal git push may be rejected—the remote still points at the old hashes.
Force push moves the remote branch tip to match your local rewritten history:
git push --force origin my-feature
Prefer --force-with-lease: it refuses to push if someone else updated that branch since your last fetch, instead of blindly overwriting their commits.
git push --force-with-lease origin my-feature
Rules:
- Treat
main/masteras sacred unless your team explicitly allows history rewrites there. --force-with-leaseis for your feature branches after a clean rebase—or when you coordinate with teammates.- When in doubt,
fetch, ask in chat, or open a PR instead of forcing shared history.
Quick recap #
| Goal | Command |
|---|---|
| See remotes | git remote -v |
| First upload | git push -u origin BRANCH |
| Daily upload | git push |
| Download remote commits | git pull |
| Fresh copy | git clone URL |
| Change branch | git switch BRANCH |
| Fold branch into main | git switch main then git merge BRANCH |
| Stage paths / tracked-only / hunks | git add PATH · git add -u · git add -p |
| Unstage | git restore --staged PATH |
| Staged vs unstaged diff | git diff · git diff --staged |
| Replay feature on top of main | git rebase origin/main (on feature branch) |
| Edit recent commits | git rebase -i HEAD~N |
| Copy one commit | git cherry-pick HASH |
| Ignore files | .gitignore + git add / commit |
| Safe undo (shared history) | git revert HASH |
| Rewind local branch | git reset (know what you are discarding) |
| Push after rewriting history | git push --force-with-lease origin BRANCH |
Closing #
You now have a broader map for local Git + GitHub: publish work, pull updates, ignore clutter, merge or rebase, cherry-pick isolated fixes, stage with intention (-p, -u), and reach for --force-with-lease only when you understand whose commits you might overwrite.
If Part 1 was about trusting your own commits on disk, Part 2 is about letting someone else’s machine—or Future You—pick up the same story.
Thanks for reading. Questions and war stories welcome; the Git docs remain the ground truth when commands evolve.
Series: Part 1 — local repo basics · Part 2 — remotes & cleanup (you are here)