Matthew Lang avatar

Git

Core commands and concepts worth having at hand — not exhaustive, just the essentials.

The three states

Working directory → staging area (index) → repository (committed).

git status              # what's changed / staged
git add <file>          # working dir -> staging
git add -p              # stage interactively, hunk by hunk
git commit -m "msg"     # staging -> repo
git commit -am "msg"    # stage all tracked changes + commit in one step

History & inspection

git log --oneline --graph --decorate
git log -p <file>            # full diffs per commit for a file
git diff                     # working dir vs staging
git diff --staged            # staging vs last commit
git blame <file>              # who changed each line, and when
git show <commit>             # full diff of one commit

Branching

git branch                    # list local branches
git switch -c feature/thing   # create + switch (modern replacement for checkout -b)
git switch main               # switch back
git branch -d feature/thing   # delete (merged)
git branch -D feature/thing   # delete (force, unmerged)

Merging & rebasing

git merge feature/thing       # merge into current branch, creates a merge commit
git rebase main               # replay current branch's commits on top of main
git rebase -i HEAD~3          # interactive: reword/squash/drop last 3 commits
  • Merge preserves history exactly as it happened, including a merge commit.
  • Rebase rewrites history to look linear — never rebase commits that are already pushed and shared, since it changes their SHAs.
  • Interactive rebase actions: pick, reword, edit, squash (s), fixup (f, like squash but discards the message), drop.

Undoing things

git restore <file>                 # discard uncommitted working-dir changes
git restore --staged <file>        # unstage, keep working-dir changes
git reset --soft HEAD~1            # undo last commit, keep changes staged
git reset --mixed HEAD~1           # undo last commit, keep changes unstaged (default)
git reset --hard HEAD~1            # undo last commit, discard changes entirely
git revert <commit>                # new commit that undoes an earlier one (safe for shared history)

Rule of thumb: reset rewrites history (fine locally, dangerous once pushed); revert adds new history (safe always).

Stashing

git stash                     # shelve working-dir + staged changes
git stash -u                  # also stash untracked files
git stash list
git stash pop                 # reapply + drop from stash list
git stash apply stash@{1}     # reapply a specific stash, keep it in the list

Remotes

git remote -v
git fetch origin              # download refs/objects, don't touch working dir
git pull                      # fetch + merge (or rebase, with --rebase / pull.rebase=true)
git push origin feature/thing
git push -u origin feature/thing   # set upstream tracking on first push

Cherry-picking & tags

git cherry-pick <commit>      # apply one specific commit onto the current branch
git tag v1.2.0
git tag -a v1.2.0 -m "release notes"
git push origin v1.2.0
git push origin --tags

Resolving conflicts

  1. Conflicting files show <<<<<<<, =======, >>>>>>> markers.
  2. Edit to the resolved content, remove the markers.
  3. git add <file> to mark resolved.
  4. git commit (merge) or git rebase --continue (rebase).
  5. Bail out entirely with git merge --abort or git rebase --abort.

.gitignore basics

*.log
/tmp/
.env
!important.log        # negate a pattern, un-ignore a specific file

Already-tracked files aren’t affected by .gitignore — untrack with git rm --cached <file> first.

Conventional commit format (if you’re using it)

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Common types: feat, fix, docs, style, refactor, perf, test, build, ci, chore. A ! after the type/scope (feat!:) or a BREAKING CHANGE: footer marks a breaking change.

Handy aliases

git config --global alias.co switch
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --decorate --all"