Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
What Are Git and GitHub? An Introduction to Version Control
Why version control exists, how centralized and distributed tools differ and why Git and GitHub are not the same thing. We try distributed work by reading history and committing in a clone whose server is gone, then look at Git's short history, its place in DevOps and how the series is organized.
Installing Git and First Settings: Starting Right with git config
We install Git on macOS, Windows and Linux, check the version and look at the system/global/local config layers, user.name and user.email, why init.defaultBranch main matters, core.editor and core.autocrlf. We compare the git config list/get/set/unset subcommands (2.46+) with the old --get form.
Your First Git Repo: git init, the Staging Area and the First Commit
We build the bookstore repo from scratch with git init and take a first look inside the .git folder. We walk through the working tree, staging area and repository with git status, git add and git commit, and learn to read the two columns of status -s and why an MM file commits its staged version.
Inside a Git Commit: Snapshots, Objects and Hashes
We open commit, tree and blob objects with git cat-file to see that a commit is a snapshot, not a diff, compute a hash by hand with shasum and find out why an unchanged file is not stored twice. We cover the rules of a good commit message and why git commit --amend creates a new commit.
Tracking Files with Git: .gitignore, git rm --cached and git mv
We look at .gitignore patterns, exceptions with ! and how git check-ignore -v shows which rule applies. We see why an already committed .env stays tracked despite .gitignore and how git rm --cached untracks it, then cover global excludes, git mv and line endings with .gitattributes.
Looking at Git History: git log, git show, git blame and Aliases
We move around history with git log's --oneline, --graph, --stat, -p, --format, --author, --since, --grep and --follow options and see the difference between -S and -G on a line whose price changed. We inspect a single commit and an old file version with git show, trace lines with git blame -L and shorten long commands with aliases.
Comparing Changes with Git diff
We see with real output which comparison git diff makes between the working tree, the index and HEAD, how to read diff output, summary views like --stat, --name-only and --word-diff, diffs between commits, and the difference between two dots and three dots (--merge-base).
Git Branch: A Movable Pointer, HEAD and git switch
We see with real output that a branch is a 41-byte file holding a single commit hash, how HEAD works, listing, renaming and deleting with git branch, moving around with git switch and switch -c, getting into and out of detached HEAD, and the old use of git checkout.
Git Merge: Fast-forward, Three-way Merge and the Merge Commit
We see with real output the difference between fast-forward and three-way merge, the role of the common ancestor (git merge-base), the inside of a two-parent merge commit, the --no-ff and --ff-only options, the ort strategy that has been the default since Git 2.34, and cleaning up branches after a merge.
Resolving Git Conflicts: Markers, merge --abort and zdiff3
We see with real output why conflicts happen, how to read the markers, how to inspect the state with git status, git log --merge and git ls-files -u, resolving step by step, git merge --abort, merge.conflictStyle zdiff3, --ours/--theirs, mergetool and rerere, with a short note on git add --resolved in Git 2.56.
Git Remote and Clone: origin, fetch, push and Upstream
We see with real output what a remote is, git remote add, push -u and the upstream setting with a local bare repo standing in for GitHub, remote-tracking branches like origin/main, what git clone does, the split between fetch and merge, sharing a new branch, git remote show/rename and a rejected push.
Understanding Git Pull: fetch, merge, rebase and Divergent Branches
We see with real output that git pull is fetch plus merge or rebase, the "divergent branches" error on diverged branches since Git 2.33.1, the --no-rebase, --rebase and --ff-only options, the choice between pull.rebase and pull.ff, pull.autostash from Git 2.51 and fetch --prune.