Everyday
Getting Started
Set your name & email
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
Without --global, the setting applies only to the current repo.
Initialize a new repo
git init
Clone an existing repo
git clone <url>
git clone <url> <directory>
Set default branch name
git config --global init.defaultBranch main
Making Changes
Show working tree status
git status
Stage files
git add <file>
git add .
Stage hunks interactively
git add -p
Unstage a file (keep changes)
git restore --staged <file>
Commit staged changes
git commit -m "message"
Stage & commit all tracked files
Skips git add for files Git already tracks. Does not add new untracked files.
git commit -am "message"
Move, rename, or delete
git mv <old> <new>
git rm <file>
git rm --cached <file>
--cached untracks without deleting the file.
Stashing
Stash changes
Saves uncommitted changes and reverts the working directory. Useful for switching branches without committing.
git stash
List stashes
git stash list
Restore & delete most recent stash
git stash pop
Restore but keep the stash
git stash apply
Drop a specific stash
git stash drop stash@{n}
Branching
List branches
git branch
git branch --sort=-committerdate
Create a branch
git branch <name>
Switch to a branch
git switch <name>
Create & switch
git switch -c <name>
Delete a branch (safe)
Fails if the branch has unmerged changes.
git branch -d <name>
Delete a branch (force)
git branch -D <name>
Check out a specific commit
Creates a detached HEAD — you’re not on any branch.
git checkout <commit>
To start a branch from that point:
git switch -c <name> <commit>
Inspect & Sync
Viewing Changes
Show unstaged changes
git diff
Show staged changes
git diff --staged
Show all changes (staged + unstaged)
git diff HEAD
Compare two branches
git diff main..feature
Diff a file since a commit
git diff <commit> -- <file>
Summary of changes
git diff <commit> --stat
Show a specific commit
git show <commit>
Diff two commits
git diff <commit1> <commit2>
History & Blame
Show commit history
git log --oneline
History with graph
git log --oneline --graph --all
Commits that modified a file
git log <file>
Follow file through renames
git log --follow <file>
Find commits that added or removed text
git log -G "pattern"
Who last changed each line
git blame <file>
Push & Pull
Push to remote
git push origin main
Push & set upstream tracking
Links local branch to remote so future push/pull work without arguments.
git push -u origin <branch>
Force push (safe)
Fails if someone else pushed first.
git push --force-with-lease
Fetch changes (don’t merge)
git fetch origin
Fetch & prune deleted remote branches
git fetch --prune
Pull (fetch + merge)
git pull
Pull with rebase
git pull --rebase
Remote Setup
Add a remote
git remote add <name> <url>
List remotes
git remote -v
Rename / remove a remote
git remote rename <old> <new>
git remote remove <name>
Show remote details
git remote show origin
See which branch tracks which remote
git branch -vv
Set upstream for existing branch
git branch -u origin/<branch>
List / check out remote branches
git branch -r
git switch <remote-branch>
Delete a remote branch
git push origin --delete <branch>
Integrate
Merging
Merge a branch into current
Creates a merge commit that joins both histories.
git merge <branch>
Fast-forward merge
When main has no new commits, the pointer moves forward. No merge commit needed.
Squash merge
Combines all branch commits into one on the target.
git merge --squash <branch>
git commit -m "message"
Rebasing
Rebase current branch onto another
Replays your commits on top of the target, creating linear history. Rewrites commit hashes.
git switch feature
git rebase main
Before — branches have diverged:
After git rebase main — linear history:
Interactive rebase (last N commits)
Squash, reorder, edit, or drop commits.
git rebase -i HEAD~<n>
Verbs: pick keep, squash meld into previous, fixup meld & discard message, reword change message, edit pause to amend, drop remove.
After rebase, force push to update remote
git push --force-with-lease
Cherry-Pick & Tags
Cherry-pick a commit
Copies a single commit onto the current branch.
git cherry-pick <commit>
Create a tag
git tag <name>
Create an annotated tag
git tag -a <name> -m "message"
Push tags to remote
git push --tags
Resolving Conflicts
When do conflicts happen?
When two branches change the same lines, or one deletes a file the other modified.
Conflict markers
<<<<<<< HEAD
your changes
=======
their changes
>>>>>>> feature-branch
Edit the file to keep the correct code, then remove all markers.
After resolving, stage & continue
git add <file>
git merge --continue
git rebase --continue
git cherry-pick --continue
Abort & go back
git merge --abort
git rebase --abort
git cherry-pick --abort
Accept all of theirs or ours
git checkout --theirs <file> && git add <file>
git checkout --ours <file> && git add <file>
Fix Mistakes
Undoing Local Changes
Discard unstaged changes to a file
git restore <file>
Discard all staged & unstaged changes to a file
git restore --staged --worktree <file>
Discard all unstaged changes
git restore .
Discard everything (staged + unstaged)
git reset --hard
Delete untracked files
Preview first with -n, then run with -f.
git clean -n
git clean -f
Reverting Commits
Revert a commit
Creates a new undo commit. Safe for shared branches — doesn’t rewrite history.
git revert <commit>
Before — C introduced a bug:
After git revert C — bug undone, history preserved:
Revert without auto-committing
git revert --no-commit <commit>
Revert a merge commit
-m 1 keeps the first parent (the branch you merged into).
git revert -m 1 <merge-commit>
Revert a range of commits
git revert <oldest>^..<newest>
Rewriting History
Amend last commit message
git commit --amend -m "new message"
Add forgotten files to last commit
git add <file>
git commit --amend --no-edit
Undo last commit, keep changes staged
git reset --soft HEAD~1
Undo last commit, keep changes unstaged
git reset HEAD~1
Undo last commit, discard changes
git reset --hard HEAD~1
Restore a file from another commit
git restore <file> --source <commit>
Recover lost commits
reflog shows everywhere HEAD has pointed.
git reflog
git reset --hard <commit>
Commit References
By name, tag, or hash
main, feature/login, v1.0, 3e887ab, origin/main
HEAD — current commit
HEAD
~ walks back linearly
HEAD~1 # one commit back
HEAD~3 # three commits back
^ picks a parent (for merges)
HEAD^ # first parent (same as HEAD~1)
HEAD^2 # second parent of a merge
Combine them
HEAD~2^2 # back 2, then second parent
Ranges
git log main..feature # in feature, not main
git log main...feature # in either, not both
Practices & Patterns
Naming & Messages
Branch naming conventions
Prefixes create logical grouping in tools and listings.
feature/<name>— new functionalitybugfix/<name>— fixing a bughotfix/<name>— urgent production fixrelease/<name>— preparing a releasechore/<name>— maintenance, docs
git switch -c feature/user-login
git switch -c bugfix/null-pointer
git switch -c hotfix/security-patch
Commit message conventions
feat: add user authentication
fix: prevent null pointer on login
docs: update API reference
refactor: extract validation logic
test: add login unit tests
chore: update dependencies
Workflows
GitHub Flow (simple)
One long-lived branch. Features branch off, get reviewed via PR, merge back.
git switch -c feature/thingfrommain- Commit, push, open a pull request
- Review, then merge PR into
main - Deploy from
main
GitFlow (structured releases)
main for production, develop for integration.
feature/*→ branches off & merges todeveloprelease/*→ branches offdevelop, merges tomain+develophotfix/*→ branches offmain, merges tomain+develop
Trunk-based development
Everyone commits to main (or short-lived branches merged within a day). Relies on feature flags and CI.
Gitignore
Pattern syntax
*.log # any .log file
build/ # directory named build
/TODO # only root TODO, not sub/TODO
!important.log # negate: do track this file
**/debug # match in any subdirectory
doc/*.txt # doc/notes.txt but not doc/a/b.txt
Remove a tracked file from the repo
git rm --cached <file>
File stays on disk but leaves version control. Commit afterward.
Global ignore
git config --global \
core.excludesFile ~/.gitignore_global
Check what rule is ignoring a file
git check-ignore -v <file>
.gitkeep convention
Git won’t track empty directories. Drop a .gitkeep inside to force-track them. This is a community convention, not a Git feature.
Reference
Config & Tools
Set your diff tool
git config --global diff.tool vscode
git config --global difftool.vscode.cmd \
'code --wait --diff $LOCAL $REMOTE'
Set your merge tool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd \
'code --wait $MERGED'
Create aliases
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
Set the default pager
git config --global core.pager 'less -FX'
Important files
.git/config— local repo config~/.gitconfig— global user config.gitignore— files to exclude from tracking
Key Concepts
- repository — a project folder tracked by Git with full change history
- commit — a snapshot of staged changes with a descriptive message
- branch — a movable pointer to a commit; isolates work
- HEAD — pointer to your current commit (usually tip of a branch)
- staging area — where you prepare changes before committing (
git add) - working tree — the actual files on disk
- remote — a repo hosted elsewhere (e.g. GitHub);
originis the default - tracking branch — local branch linked to a remote for easy push/pull
- merge — combines two branches via a new commit
- rebase — replays commits on another branch for linear history
- fast-forward — merge where the pointer just moves forward (no new commit)
- conflict — same lines changed on both sides; must resolve manually
- stash — temporary shelf for uncommitted changes
- tag — permanent label on a commit, typically for releases
- reflog — log of everywhere HEAD has pointed; safety net for lost commits
- cherry-pick — copy one commit onto another branch
- revert — new commit that undoes a previous commit
- reset — move HEAD to a different commit; can rewrite history