Git
Setup And Config
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main
git config --global core.editor "code --wait"
git config --list # show effective config
git config --global alias.st status # custom alias
Config is layered: --system < --global < --local (repo-level, no flag). Local overrides global.
Basic Workflow
git init # new repo
git clone <url> # copy existing repo
git status # working tree state
git add <file> # stage
git add -p # stage interactively, hunk by hunk
git add . # stage everything in cwd
git commit -m "message" # commit staged changes
git commit -am "message" # stage tracked-file changes + commit
git push # send commits to remote
git pull # fetch + merge from remote
Working tree → staging area (index) → local repo → remote. Only staged changes are included in the next commit.
Branching
git branch # list local branches
git branch -a # list all (local + remote)
git branch <name> # create branch
git switch <name> # checkout a branch (modern)
git switch -c <name> # create + switch
git checkout <name> # older equivalent
git branch -d <name> # delete (safe, merged only)
git branch -D <name> # force delete
Convention: feat/, fix/, chore/ prefixes for descriptive branch names; keep branches short-lived and focused on one change.
Merging And Rebasing
git merge <branch> # merge <branch> into current, creates merge commit
git merge --no-ff <branch> # always create a merge commit (preserves history shape)
git rebase <branch> # replay current branch's commits onto <branch>
git rebase -i HEAD~3 # interactive rebase: reorder/squash/edit last 3 commits
git rebase --continue # after resolving a conflict mid-rebase
git rebase --abort # bail out, restore pre-rebase state
Merge preserves true history (non-destructive); rebase rewrites commit hashes (linear history, but never rebase commits already pushed/shared with others).
Remote Workflow
git remote -v # list remotes
git remote add origin <url> # add a remote
git fetch origin # download refs, no merge
git push -u origin <branch> # push + set upstream tracking
git push origin --delete <branch> # delete remote branch
git pull --rebase # rebase local commits on top of fetched ones
fetch updates your local view of the remote without touching your working tree; pull = fetch + merge (or --rebase).
Undoing Changes
git restore <file> # discard unstaged changes to a file
git restore --staged <file> # unstage (keep working tree changes)
git checkout -- <file> # older equivalent of restore
git reset --soft HEAD~1 # undo last commit, keep changes staged
git reset --mixed HEAD~1 # undo last commit, unstage changes (default)
git reset --hard HEAD~1 # undo last commit, discard changes — destructive
git revert <commit> # new commit that undoes <commit> — safe for shared history
reset rewrites history (avoid on pushed/shared commits); revert adds a new commit and is always safe to use on shared branches.
Stashing
git stash # save working tree + index, revert to clean state
git stash -u # also stash untracked files
git stash list # show stashes
git stash pop # apply + remove most recent stash
git stash apply stash@{1} # apply a specific stash, keep it in the list
git stash drop stash@{1} # remove without applying
Use stash to quickly switch context (e.g. urgent hotfix) without committing half-finished work.
Inspecting History
git log --oneline --graph --all # compact visual history
git log -p <file> # history with diffs for a file
git blame <file> # who last touched each line
git diff # unstaged changes vs. index
git diff --staged # staged changes vs. last commit
git show <commit> # show a specific commit's changes
git log --author="Ana" --since="2 weeks ago"
Tags And Releases
git tag v1.0.0 # lightweight tag on HEAD
git tag -a v1.0.0 -m "Release 1.0" # annotated tag (recommended — stores author/date/message)
git tag # list tags
git push origin v1.0.0 # push a single tag
git push origin --tags # push all tags
git tag -d v1.0.0 # delete local tag
Conflict Resolution
# after a conflicting merge/rebase, git marks the file:
# <<<<<<< HEAD
# your version
# =======
# their version
# >>>>>>> branch-name
git status # lists conflicted files
# edit the file, remove the markers, keep the correct content
git add <file> # mark as resolved
git commit # (merge) or:
git rebase --continue # (rebase)
git diff # review before committing/continuing
git merge --abort # bail out entirely, restore pre-merge state
Gitignore Hygiene
# .gitignore
node_modules/
dist/
.env
*.log
.DS_Store
git rm -r --cached node_modules # stop tracking a dir already committed by mistake
git check-ignore -v <file> # debug why a file is (or isn't) ignored
Never commit secrets — if one lands in history, rotate it immediately and scrub history with git filter-repo (not just a new commit, since old commits still contain it).