Git and GitHub Master Reference
One-stop reference for day-to-day Git, creating repos with gh, and SSH authentication on Linux/Windows. Fast commands and safe workflows without hunting docs.
Quick Index
- 0) Core mental models
- 1) Git essentials
- 2) Undoing changes
- 3) Stashing
- 4) Tags
- 5) .gitignore
- 6) Common workflows
- 7) Create a private repo with gh
- 8) GitHub SSH authentication
- 9) Auto-loading SSH keys
- 10) Appendix
Legend: Replace placeholders like <repo_url>, <branch>, <file>, and <commit_hash>.
Core Mental Models
Local vs Remote
- Local repo: The
.gitfolder on your machine (commits, branches, staging index). - Remote: A hosted copy (GitHub) with its own branches and history.
Three places a change can live
- Working tree: your edited files
- Staging area (index): what will go into the next commit
- Commit history: what already got recorded
Git Essentials
Basic commands
| Command | Description |
|---|---|
git clone <repo_url> | Clone a repository from a URL. |
git init | Initialize a new Git repository in the current directory. |
git status | Show repo status (modified, staged, untracked). |
git help <command> | Built-in help for any command. |
Staging and committing
| Command | Description |
|---|---|
git add <file> | Stage a file for commit. |
git add . | Stage all changes in the current directory (use carefully). |
git commit -m "message" | Commit staged changes with a message. |
git commit --amend | Replace the last commit (only safe if not pushed/shared). |
git diff | Show unstaged changes. |
git diff --staged | Show staged (but uncommitted) changes. |
git reset <file> | Unstage a file (keeps working tree changes). |
Viewing history
| Command | Description |
|---|---|
git log | Show commit history. |
git log --oneline | Condensed one-line history. |
git log --oneline --decorate --graph -n 20 | Fast “what’s going on” view. |
git show <commit_hash> | Show a specific commit (metadata + diff). |
Branching (classic and modern)
| Task | Classic | Modern |
|---|---|---|
| List branches | git branch | git branch |
| Create branch | git branch <name> | git switch -c <name> |
| Switch branch | git checkout <name> | git switch <name> |
| Create + switch | git checkout -b <name> | git switch -c <name> |
| Delete local branch | git branch -d <name> | git branch -d <name> |
Merging
| Command | Description |
|---|---|
git merge <branch_name> | Merge branch into current branch. |
git merge --no-ff <branch_name> | Force a merge commit (keeps branch history visible). |
git mergetool | Launch merge tool (if configured). |
Remotes (push/pull/fetch)
| Command | Description |
|---|---|
git remote -v | Show remote URLs. |
git remote add origin <repo_url> | Add a remote named origin. |
git fetch origin | Fetch remote updates without merging. |
git pull origin <branch> | Fetch + merge from remote branch. |
git push origin <branch> | Push branch to remote. |
git push -u origin <branch> | Push and set upstream tracking. |
Undoing Changes
Safe vs destructive (quick table)
| Goal | Preferred (safer) | Risky / destructive |
|---|---|---|
| Undo a commit that is already pushed/shared | git revert <commit_hash> | Avoid reset --hard on shared history |
| Throw away ALL local changes | (stash first if unsure) | git reset --hard |
| Remove untracked files | git clean -n (preview) | git clean -fd (delete) |
| Fix last commit message/content | git commit --amend (only if not pushed) | Rewriting pushed commits hurts teammates |
Rule of thumb: If it is already pushed, prefer revert over reset --hard.
Common “oops” recipes
- Discard edits in one file (restore to last commit):
git restore <file>- Unstage a file but keep edits:
git reset <file>- Restore file from a specific commit:
git restore --source <commit_hash> -- <file>- Hard reset to match remote main (dangerous; discards local commits and changes):
git fetch origin
git reset --hard origin/mainWarning: reset --hard is permanent for unpushed work. Use only when you are sure.
Stashing
| Command | Description |
|---|---|
git stash | Stash tracked changes (default). |
git stash -u | Include untracked files. |
git stash list | Show stashes. |
git stash pop | Apply most recent stash and remove it. |
git stash apply stash@{0} | Apply a specific stash (keeps it). |
git stash drop stash@{0} | Delete a stash entry. |
Named stash (recommended):
git stash push -m "wip: dns change testing"Tags
| Command | Description |
|---|---|
git tag <tag_name> | Create lightweight tag at current commit. |
git tag -a v1.2.3 -m "release v1.2.3" | Create annotated tag (preferred for releases). |
git push origin <tag_name> | Push one tag. |
git push origin --tags | Push all tags. |
.gitignore
Add a new ignore rule
Edit/create .gitignore, then commit it.
If a file is already tracked, ignoring will not remove it
You must untrack it once:
git rm --cached <file_or_folder>
git commit -m "Stop tracking <file_or_folder>"Common Workflows
A) Typical feature branch → PR
git checkout main
git pull origin main
git checkout -b feature/my-change
# work...
git add .
git commit -m "Implement my change"
git push -u origin feature/my-changeThen open a Pull Request on GitHub.
B) Update your branch with main (merge approach)
git checkout main
git pull origin main
git checkout feature/my-change
git merge mainC) Update your branch with main (rebase approach; cleaner history, more footguns)
Only do this if your team is OK with rebasing.
git checkout feature/my-change
git fetch origin
git rebase origin/mainIf conflicts happen:
# fix files
git add <fixed_files>
git rebase --continueAbort rebase:
git rebase --abortD) Cherry-pick one commit into current branch
git cherry-pick <commit_hash>Create a Private GitHub Repo with gh
Prereqs
- Git installed
- GitHub CLI installed (
gh) - Authenticated:
gh auth login
Option A: Create repo from an existing local folder (common)
Run inside your project folder:
gh repo create my-new-repo --private --description "My private repo" --source=.Make sure you have at least one commit, then push:
git status
git add .
git commit -m "Initial commit"
git push -u origin mainOption B: Create repo first, then initialize locally
mkdir my-new-repo
cd my-new-repo
git init
echo "# My New Repository" > README.md
git add README.md
git commit -m "Initial commit"
gh repo create my-new-repo --private --description "My private repo" --source=. --remote=origin
git push -u origin mainVerification
git status
git remote -v
gh auth status
gh repo view --webTroubleshooting
- Wrong remote URL:
git remote -v
git remote set-url origin <correct_url>mainvsmastermismatch:
git branch -M main
git push -u origin mainGitHub SSH Authentication
Steps
- Check existing keys
ls -al ~/.ssh- Generate a new key (prefer ed25519)
ssh-keygen -t ed25519 -C "your_email@example.com"Legacy RSA (only if needed):
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"- Start ssh-agent and add your key
Linux/macOS:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519If RSA:
ssh-add ~/.ssh/id_rsa- Copy public key to clipboard
Linux:
xclip -sel clip < ~/.ssh/id_ed25519.pubWindows (Git Bash):
cat ~/.ssh/id_ed25519.pub | clip-
Add key to GitHub
GitHub → Settings → SSH and GPG keys → New SSH key → paste → save -
Test SSH
ssh -T git@github.comAuto-Loading SSH Keys
Linux: basic agent auto-start (shell startup)
Add to ~/.bash_profile or ~/.profile:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519Linux: keychain (more convenient across sessions)
eval "$(keychain --eval --agents ssh id_ed25519)"Windows 10/11: built-in OpenSSH Agent (PowerShell as Admin)
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add ~\.ssh\id_ed25519Appendix
A) First-time identity config
git config --global user.name "Your Name"
git config --global user.email "your_email@example.com"B) SSH vs HTTPS remotes
- SSH:
git@github.com:ORG/REPO.git - HTTPS:
https://github.com/ORG/REPO.git
Switch existing repo to SSH:
git remote set-url origin git@github.com:ORG/REPO.git
git remote -vC) Quick sanity checklist before pushing
git statusis clean except what you intend- You are on the right branch:
git branch - Remote is correct:
git remote -v - Pull latest main before PR:
git checkout mainthengit pull origin main