Under the hood of Git — objects, refs, rebase, reflog recovery, and branching strategies.
Welcome everyone! Today we're diving deep into Git Internals and Advanced Workflows. We'll go under the hood of the world's most popular version control system to understand how Git actually works at a fundamental level. We'll explore the object model, look at different branching strategies, and cover some advanced techniques that will make you more effective with Git in your daily work. Whether you're already comfortable with basic Git commands or looking to level up your version control skills, this session will give you insights into what's really happening when you commit, branch, and merge. Let's get started.
Let's start by understanding Git's object model, shown in this diagram. Git uses four core object types. Content objects include blobs, which store file contents, and trees, which represent directory listings. History objects include commits, which capture snapshots plus metadata like author and timestamp, and tags for annotated references. Then we have references: branch pointers under refs/heads, HEAD which points to your current branch, and remote tracking branches. Looking at the relationships, commits point to trees, trees point to blobs and other trees, and commits can point to parent commits forming your history. This content-addressable structure is what makes Git so powerful and efficient. Everything is identified by its SHA-1 hash, making data corruption nearly impossible to miss.
Now let's see how commits actually work under the hood using Git's plumbing commands. Looking at this terminal output, when we inspect HEAD with cat-file, Git tells us it's a commit object. Using cat-file with the -p flag shows us the commit's contents: it references a tree object, a parent commit, author and committer information, and the commit message. When we inspect that tree object, we see it contains file entries like README and package.json as blobs, plus a subdirectory as another tree. Finally, inspecting a blob shows us the actual file content. This layered structure means Git can efficiently store your entire project history. Identical files across commits share the same blob, and Git only stores the differences in trees and commit metadata.
Let's talk about branching strategies. In this diagram, we see a feature branch diverging from main. The standard merge creates a merge commit M4 that ties the histories together, preserving the complete branch structure. The rebase alternative shows commits F1 and F2 being replayed on top of M3, creating new commit hashes shown in green. The table compares three strategies: git merge preserves full history but creates merge commits, git rebase gives you clean linear history but rewrites hashes, and git merge squash condenses a feature into a single commit but loses granular history. Choose merge when you want to preserve the context of how work was done, rebase when you want a clean story, and squash when a feature represents one logical unit of change.
Interactive rebase is incredibly powerful for cleaning up your commit history. Looking at the before state, we have a messy history with WIP commits and typo fixes scattered throughout. Running git rebase -i HEAD~5 opens an editor where we can reorganize these commits. In this example, we keep the initial auth module commit and squash all the others into it. After completing the rebase, our log shows just two clean commits: the authentication feature and the initial setup. This is perfect before opening a pull request. Your teammates see a logical, reviewable history instead of your debugging journey. Just remember: only rebase commits that haven't been pushed to a shared branch. Once others have your commits, they're part of the permanent record.
Different teams need different Git workflows, and we have four major strategies here. Git Flow uses long-lived branches with separate main and develop branches, plus feature, release, and hotfix branches. It's best for scheduled releases like desktop software. Trunk-Based Development keeps a single main branch with very short-lived feature branches and multiple merges per day, ideal for continuous delivery teams. GitHub Flow is PR-centric: branch from main, open a pull request, and deploy when you merge back. This works great for SaaS products with continuous deployment. Finally, GitLab Flow uses environment branches where changes flow from main to staging to production, perfect for managing multiple deployment environments. Choose the workflow that matches your team's release cadence and deployment model.
The reflog is Git's ultimate safety net. In this example, we accidentally hard reset back three commits, losing work. Many developers would panic here, but reflog remembers everything. Running git reflog shows a chronological list of HEAD movements, including that reset operation at the top and our rebase operation just before it. The commit we want, e5f6a7b, is still there at HEAD@{1}. We can recover by resetting hard back to that hash. After recovery, our log shows all three commits restored. Reflog entries persist for 90 days by default, so you have a generous window to fix mistakes. This is why you can be bold with Git operations. Almost anything short of deleting the .git directory is recoverable if you know about reflog.
Git hooks let you automate quality checks and enforce standards. This pre-commit hook runs before every commit is created. First it runs ESLint to check code style and fix auto-fixable issues. If linting fails, the script exits with code 1, aborting the commit. Then it runs TypeScript's type checker. The hook's exit code determines whether the commit proceeds. Hooks live in .git/hooks and are shell scripts, so you can run any command-line tool. Common hooks include pre-commit for linting, commit-msg for validating message format, pre-push for running tests before pushing, and post-merge for installing dependencies after pulling. Tools like Husky make managing hooks across your team easier by storing them in version control instead of the .git directory.
Let's look at Git's incredible adoption. GitHub alone hosts over 200 million repositories, with 4 billion commits pushed daily. More than 100 million developers use Git worldwide, and surveys show 94% of developers prefer Git over other version control systems. The timeline shows Git's rapid rise: created by Linus Torvalds in 2005, GitHub launched in 2008, and by 2013 Git had surpassed Subversion in adoption. Microsoft's acquisition of GitHub in 2018 was a strong endorsement, and just last year GitHub reached 100 million developers. These aren't just impressive numbers, they mean Git has the largest community, the best tooling, and the most learning resources of any version control system. When you learn Git deeply, you're investing in a skill that's universally valued.
Let's talk about common mistakes that can cause serious problems. The warning callout highlights the three most destructive: force pushing overwrites others' work, rewriting shared history creates conflicts, and committing secrets is nearly impossible to fully undo. Looking at the cards, force pushing to shared branches is dangerous, so use --force-with-lease which aborts if the remote has commits you haven't fetched. Committing secrets like API keys is permanent in Git history, so use .gitignore from day one and tools like git-secrets to scan for leaks. Giant binary files bloat your repository forever even if deleted later, so use Git LFS for binaries. And rebasing public history creates duplicate commits with different hashes, confusing everyone, so only rebase local unpushed work. Following these guidelines will save you and your team from painful recovery scenarios.
Let's recap the key takeaways from today. First, remember that Git stores snapshots, not diffs. Blobs, trees, and commits form a content-addressable directed acyclic graph, which is why Git is so fast and reliable. Second, interactive rebase is your tool for maintaining clean history. Squash those WIP commits before merging so your main branch tells a clear story. Third, reflog is your undo button. It recovers lost commits for 90 days by default, so don't be afraid to experiment. And finally, pick the right workflow for your team. Trunk-based development for speed and continuous delivery, Git Flow for scheduled releases with multiple release branches. Understanding these internals and workflows will make you much more effective with Git. Thanks for your attention, and happy committing!
Hands-on implementation guides with detailed code examples, step-by-step instructions, and expanded explanations for each topic.