Pro Git Ch2 — Git Basics
- Description: Notes on Pro Git (2nd ed.) Chapter 2 — initializing/cloning repos, recording changes (
add/commit/rm/mv/.gitignore/diff), viewing history (log/show/reflog), undoing things (restore/reset/revert/amend), working with remotes, tagging, aliases. Plusgit stash(technically Pro Git §7.3) placed here for workflow proximity. - My Notion Note ID: K2B-2-2
- Created: 2020-06-02
- Updated: 2026-05-19
- License: Reuse is very welcome. Please credit Yu Zhang and link back to the original on yuzhang.io
Table of Contents
- 1. Getting a Git Repository
- 2. Recording Changes
- 3. Viewing Commit History
- 4. Undoing Things
- 5. Working with Remotes
- 6. Tagging
- 7. Aliases
- 8. git stash (aside)
- 9. References
1. Getting a Git Repository
1.1 git init
git init— turn current directory into a Git repo (creates.git/).git init --bare— bare repo (no working tree); used for server-side hosting.
1.2 git clone
git clone <url> [name]— full copy including history; optional rename.- URL schemes:
- SSH:
[email protected]:user/repo.git - HTTPS:
https://github.com/user/repo.git - Git (read-only):
git://github.com/user/repo.git - Local:
/path/to/repoorfile:///path/to/repo
- SSH:
git clone -o <remote>— set remote name (defaultorigin).git clone --depth <n>— shallow clone (last n commits only — saves disk/bandwidth).git clone --branch <branch>— clone a single branch.
2. Recording Changes
File lifecycle: untracked → (add) → staged → (commit) → tracked/unmodified → (edit) → modified → (add) → staged → ...
2.1 git status
git status— staging snapshot.git status -s/--short— compact:MM= staged+modified,??= untracked,A= newly staged.
2.2 .gitignore
- Glob rules:
*,?,[abc]. #— comment.!— negate (re-include).- Leading
/— anchor (no recursive match). - Trailing
/— directory only. - Templates: github.com/github/gitignore.
2.3 git diff
git diff— working tree vs staged (unstaged changes).git diff --staged/--cached— staged vs last commit.git diff <commit>..<commit>— between two commits.git difftool— open in external diff tool.- VSCode as difftool:
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
2.4 git add
git add <files>— stage. Globs work.git add .= all in cwd.git add -A/--all— all changes including deletions.git add -p/--patch— interactive hunk-by-hunk staging.
2.5 git commit
git commit— open editor for message.git commit -m "msg"— one-liner.git commit -a -m "msg"— auto-stage tracked-modified files (skipsadd; does NOT add untracked).git commit --amend— replace last commit (only on unpushed commits — see § 4).
2.6 git rm
git rm <files>— delete from working tree + stage deletion.git rm -f— force when staged + modified.git rm --cached <file>— untrack but keep on disk (e.g. after committing something that should have been ignored).git rm -r <dir>— recursive.
2.7 git mv
git mv from to— rename + stage. Equivalent tomv from to; git rm from; git add to.
3. Viewing Commit History
3.1 git log
git log— full commit history (default verbose).git log -<n>— last n commits.git log --oneline— one commit per line.git log -p/--patch— show diff per commit.git log --stat— file change stats.git log --graph— ASCII branch graph.git log --decorate— show branch/tag pointers.git log --all— include all refs (not just current branch).git log --no-merges— skip merge commits.git log --pretty=<format>—oneline,short,full,fuller,format:"%h %an %s".
3.2 Filters
--since="2 weeks ago",--until=2026-01-01.--author="Jon",--committer=.--grep="bug"— match commit message.-S "func_name"— pickaxe: commits where the count of occurrences offunc_namechanged.-G <regex>— commits where any line matching regex changed (broader than-S).
3.3 Range syntax
<branch1>..<branch2>— commits in branch2 not in branch1.<a>...<b>(triple-dot, with--left-right) — symmetric difference.<not_shown>..<shown>≡<shown> ^<not_shown>≡<shown> --not <not_shown>.
3.4 git show
git show <ref>— commit/tag/blob/tree contents.git show <ref>:<path>— file at that revision.
3.5 git reflog (technically §7.1)
git reflog— local history of every HEAD update (commit, checkout, reset, merge, rebase).- Refs like
HEAD@{2},HEAD@{yesterday},<branch>@{1}. - Recovery lifeline — most "lost" commits findable here for ~90 days (default).
git reflog expire --expire=now --all— manually expire (used in large-file cleanup; see[[worktree-and-git-lfs]]§ 4.5).
4. Undoing Things
4.1 git commit --amend
- Replace the last commit (message and/or content).
- Workflow: edit,
git addforgotten files, thengit commit --amend. - ⚠️ Rewrites history → never on pushed commits.
4.2 git restore (Git 2.23+, modern)
git restore --staged <file>— unstage (keeps working-tree changes).git restore <file>— discard working-tree changes. ⚠️ Permanent loss of uncommitted edits.git restore --source=<commit> <file>— restore file content from a specific commit.git restore --staged --worktree <file>— both at once.
4.3 git reset
git reset HEAD <file>— legacy unstage (git restore --stagedsuperseded this).- Three modes affecting HEAD + index + worktree:
git reset --soft <commit>— move HEAD only; index + worktree untouched.git reset --mixed <commit>(default) — move HEAD + reset index; worktree untouched.git reset --hard <commit>— move HEAD + reset index + reset worktree. ⚠️ Destroys uncommitted work.
- Common:
git reset --soft HEAD~1— undo last commit but keep changes staged.
4.4 git checkout -- (legacy discard)
git checkout -- <file>— discard working-tree changes. ⚠️- Avoid in modern Git — use
git restore.
4.5 git revert
git revert <commit>— create a new commit that undoes the target commit.- Safe for pushed history (doesn't rewrite) → preferred way to undo published work.
git revert -m <parent-num> <merge>— revert a merge commit.
4.6 Rule of thumb
- Unshared commits:
--amend/resetare fine. - Pushed commits: use
revert.
5. Working with Remotes
5.1 git remote
git remote/-v— list remotes (with URLs).git remote add <name> <url>— add a remote.git remote show <remote>— branches, fetch/push URLs, tracking info.git remote rename <old> <new>.git remote remove <name>(orrm).git remote set-url <name> <url>— change URL.
5.2 Remote-tracking branches
<remote>/<branch>(e.g.origin/main) — local read-only pointer to remote state at last sync.- Updated by
git fetch(orgit pull). originis just convention (set byclone); not special.- View tracking + ahead/behind:
git branch -vv(cached —git fetch --allfirst for fresh). - Upstream shorthand:
@{u}or@{upstream}(e.g.git merge @{u}).
5.3 git fetch
git fetch <remote>— download new commits + update remote-tracking branches; doesn't merge.git fetch --all— all remotes.git fetch --prune— delete local remote-tracking branches whose remote was deleted.
5.4 git pull
git pull=git fetch+git merge(orgit rebaseifpull.rebase=true).- Less explicit than fetch+merge/rebase; prefer the two-step for clarity.
5.5 git push
git push <remote> <branch>— push local branch to remote of same name.git push <remote> <local>:<remote-branch>— push to different name.git push -u origin <branch>— set upstream tracking on first push.git push <remote> --delete <branch>— delete remote branch.git push --force-with-lease— safer force-push (fails if remote moved since last fetch); prefer over--force.
5.6 Tracking branches (creating from remote)
git checkout -b <local> <remote>/<branch>— create + track.git checkout --track <remote>/<branch>— auto-name.git checkout <branch>— auto-track if<branch>matches exactly one remote's branch (Git 1.6.2+).git branch -u <remote>/<branch>— set upstream on existing branch.git switch/git switch -c— modern alternative tocheckoutfor branches (Git 2.23+).
6. Tagging
- Tag = immutable named pointer to a commit (vs branch pointer, which moves).
- Lightweight — just a ref:
git tag <name>·git tag <name> <commit>.
- Annotated — full object with tagger, date, message, signature:
git tag -a <name> -m "msg".git tag -a <name> <commit> -m "msg".- Preferred for releases.
- List:
git tag·git tag -l "v1.*". - Show:
git show <tag>. - Delete local:
git tag -d <name>. - Push tags (not pushed by default):
git push <remote> <tag>— one.git push <remote> --tags— all.
- Delete remote tag:
git push <remote> --delete <tag>orgit push <remote> :refs/tags/<tag>.
7. Aliases
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
# Pretty log alias
git config --global alias.lg "log --graph --oneline --decorate --all"
# External commands — prefix with `!`
git config --global alias.visual '!gitk'
8. git stash (aside)
Technically Pro Git §7.3, placed here for workflow proximity:
git stash/git stash push— save staged + tracked-modified; restore clean working tree.git stash push -u/--include-untracked— also stash untracked.git stash push -p/--patch— interactive hunk select.git stash push -m "msg"— name the stash.git stash list.git stash apply [stash@{n}]— re-apply (keep on stack); free to apply on different branch.git stash pop— apply + drop.git stash drop [stash@{n}]— discard.git stash branch <name>— new branch from stash + apply (handy when stash conflicts with current HEAD).