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).