Git Complete Guide 2026: Branching, Rebase, Reflog, GitOps & Expert Interview Q&A
- Git Internals — Objects, Refs, and the DAG
- Branching Strategies for DevOps Teams
- Merge vs Rebase — When to Use Each
- Advanced Git Commands
- Git Reflog — Recovering Lost Commits
- Git Hooks for DevOps Automation
- GitOps — Git as Infrastructure Control Plane
- GitHub/GitLab Workflow Best Practices
- 12 Git Interview Questions with Expert Answers
Git is not just a version control tool — it is the foundation of every modern DevOps workflow. Every CI/CD pipeline is triggered by a Git event. Every GitOps deployment is driven by a Git commit. Every infrastructure change is tracked in Git. I use Git daily in production environments: maintaining branch protection rules, reviewing and approving infrastructure PRs, recovering commits after accidental force pushes, and designing monorepo workflows for platform teams. This guide covers Git at the depth required for senior DevOps and SRE interviews.
Git Internals — Objects, Refs, and the DAG
Understanding Git at the object level removes all mystery from how it works. Git is fundamentally a content-addressable key-value store. Every piece of data is stored as an object identified by its SHA-1 hash. There are four object types:
- Blob — Stores the raw content of a file. No filename, no metadata — just content. Two files with identical content share the same blob object, regardless of their names or locations.
- Tree — Represents a directory. Contains pointers to blobs (files) and other trees (subdirectories), along with filenames and permissions. A tree object encodes the complete state of a directory at a point in time.
- Commit — Points to a tree (the root of the repository at that point), one or more parent commits, and stores metadata: author, committer, timestamp, and the commit message. This forms a Directed Acyclic Graph (DAG) where each commit points backward to its parent(s).
- Tag — An annotated tag is an object pointing to a commit with a name, tagger, date, and message. Lightweight tags are just refs (pointers stored in .git/refs/tags/) pointing directly to a commit hash.
Branching Strategies for DevOps Teams
The branching strategy you choose directly impacts your CI/CD velocity, merge conflict frequency, and deployment safety. The three major strategies in use today:
Trunk-Based Development (Recommended)
All developers commit to a single main branch (the "trunk"), with feature branches lasting at most 1-2 days. Feature flags hide incomplete features from users. This strategy enables true CI (every commit integrates continuously), minimises merge conflicts (small, frequent merges), and aligns with GitOps (the trunk is always the source of truth for production). Used by Google, Meta, and Netflix.
Gitflow
Long-lived branches: main (production-ready), develop (integration), feature/*, release/*, hotfix/*. Provides clear structure for scheduled releases but creates large, painful merges and slows down CI. Best suited for software with explicit version releases (embedded systems, packaged software). Not recommended for web services deploying continuously.
GitHub Flow
Simplified: main is always deployable. Feature branches branch from main, get a PR reviewed, merge to main, deploy immediately. Simpler than Gitflow, better than Gitflow for web services, but lacking the short-lived branch discipline of true trunk-based development.
Merge vs Rebase — When to Use Each
This is the most common Git question in DevOps interviews. The choice between merge and rebase affects commit history readability and the ability to bisect bugs.
When to use rebase: Updating a local feature branch with upstream changes before opening a PR (
git pull --rebase). Cleaning up WIP commits before sharing with the team (interactive rebase to squash). When you want a clean, linear history that is easy to read and git bisect.Advanced Git Commands
Git Reflog — Recovering Lost Commits
The reflog is Git's local safety net. Every time HEAD moves (commit, checkout, rebase, reset, merge), Git records where HEAD was. The reflog is local and never pushed — it is your personal undo history for the last 90 days (configurable).
Git Hooks for DevOps Automation
Git hooks are scripts that run automatically at specific points in the Git workflow. They live in .git/hooks/ and are not committed to the repository by default. Use a tool like Husky (Node.js) or pre-commit (Python) to share hooks across the team via the repository itself.
GitOps — Git as Infrastructure Control Plane
GitOps is the practice of using Git as the single source of truth for both application code and infrastructure desired state. Every Kubernetes manifest, Terraform configuration, and Helm values file is stored in Git. Changes are made through pull requests with review and approval. A GitOps operator (ArgoCD, Flux) continuously reconciles the live environment to match the Git state. This gives: complete audit trail of every infrastructure change, instant rollback (git revert), enforced review process, and disaster recovery from Git.
GitHub/GitLab Workflow Best Practices
- Protect the main branch: Require PR reviews (at least 1 approval for features, 2 for infrastructure), require status checks to pass (CI must be green), require up-to-date branches, and disallow force pushes. This prevents direct commits to main and ensures every change has been reviewed and tested.
- Use conventional commits: Standardise commit messages with a type prefix (feat, fix, docs, chore, ci, refactor, test). This enables automatic changelog generation, semantic versioning, and makes git log scannable.
- Squash or rebase before merging: WIP commits, "fix typo", "address review comments" commits should not pollute the main branch history. Use squash merge (GitHub) or rebase and merge to produce clean, meaningful commits on main.
- Use CODEOWNERS for automatic review assignment: A CODEOWNERS file assigns automatic reviewers for specific paths. Changes to
infrastructure/require the platform team. Changes tosrc/auth/require the security team. This enforces the right experts review the right code without manual assignment. - Never commit secrets: Use pre-commit hooks with Gitleaks, GitHub's secret scanning, and .gitignore for .env files. Once a secret is committed, assume it is compromised and rotate it immediately — even if you delete it in the next commit, it remains in Git history forever.
12 Git Interview Questions with Expert Answers
git pull --rebase) and clean up WIP commits before a PR. Use merge for integrating approved PRs into main in a team environment.git reflog to see all recent HEAD positions with their SHA and a description of what moved HEAD there. Find the entry just before the reset (e.g., HEAD@{1}) and check it out: git checkout HEAD@{1} or git checkout <SHA>. Create a new branch to preserve it: git checkout -b recovery-branch. Then merge or cherry-pick the recovered commits back into your main branch. The reflog is your safety net for almost every "I destroyed my work" scenario in Git — accidental reset, deleted branch, dropped stash. The only case it cannot help with is if the reflog entries have expired (90 days) or if you ran git gc aggressively. This is why git reset --hard should be treated as a dangerous operation, especially on shared branches.git checkout <commit-sha>, git checkout v1.0.0 (a tag), or git bisect is running. In detached HEAD, any commits you make are not on any branch — they are dangling commits that will be garbage collected eventually. To save work done in detached HEAD: git checkout -b my-new-branch creates a branch at the current detached HEAD position, saving all commits you made. To return to a branch: git checkout main. If you accidentally committed in detached HEAD and switched away, use git reflog to find the SHA and recover it.git cherry-pick <fix-sha> applies just the fix to the release branch. (2) Partial feature extraction — a large feature branch has one commit that is needed urgently while the rest of the feature is still in review. (3) Reverting a revert — if a feature was reverted from main but should be re-applied after a blocking issue was fixed. Cherry-pick is not a substitute for proper branching strategy — if you are cherry-picking frequently between branches, it is a signal that the branching model needs review.git fetch followed by git merge (or git rebase if configured with pull.rebase=true). It fetches and then integrates the fetched changes into your current branch. The DevOps best practice: configure git config --global pull.rebase true so git pull does git fetch + git rebase instead of creating a merge commit for every upstream sync. This keeps your local branch history clean. Never use git pull on shared branches in a CI/CD context — always use git fetch and then explicitly merge or rebase.git bisect start, mark the current broken state as bad (git bisect bad), and mark a known-good commit or tag (git bisect good v1.4.0). Git checks out the midpoint commit between good and bad. You test it and run git bisect good or git bisect bad based on the result. Git halves the search space each time. After 10 iterations, you have identified 1 commit out of 1,024 candidates. For automated bisect, provide a test script: git bisect run npm test — Git automatically marks commits good (exit 0) or bad (non-zero exit). When complete, Git prints the first bad commit. Run git bisect reset to return to the original state. This technique finds bugs in large codebases in minutes that manual investigation would take hours.git rebase -i HEAD~5 to see the last 5 commits. Change "pick" to "squash" (or "s") for commits to fold into the one above them. Git opens an editor to combine the commit messages. Squashing is valuable because: (1) Development history contains noise — "WIP", "fix typo", "address PR comment", "forgot to add file". These are useful during development but pollute the main branch history with meaningless entries. A clean history with one meaningful commit per logical change makes git log readable and git bisect effective. (2) Squash merge (GitHub's merge strategy) automatically squashes all commits in a PR into one commit on main, named after the PR title — producing a clean linear history without any manual rebasing required from developers. This is the recommended strategy for most teams using GitHub Flow.git lfs install, git lfs track "*.psd" "*.zip" "model/*.bin", and commit the resulting .gitattributes file. When anyone clones or pulls, Git LFS automatically downloads the large files as needed. For DevOps artefacts (large Docker images, compiled binaries, ML models), the better practice is to never commit them to Git at all — store them in S3, ECR, or an artefact repository (Nexus, JFrog Artifactory) and reference them by URL or hash in your pipeline configuration.pre-commit install once after cloning to install the hooks locally. Alternatively, use Husky for Node.js projects (npm install husky) which automatically installs hooks when developers run npm install. Hooks should enforce: code formatting, linting, commit message convention (Conventional Commits), secret scanning (Gitleaks), and fast unit tests.git sparse-checkout init lets developers check out only the directories they need, reducing local clone size for large repos. (2) CODEOWNERS — automatic review assignment by directory ensures the right team reviews each service's changes. (3) Path-filtered CI — CI pipelines run only the tests and builds for the services that changed. GitHub Actions: on.push.paths filter. GitLab CI: changes keyword. (4) Merge queues — prevent parallel merges from breaking main by queuing and testing PRs sequentially or in batches before merging. (5) Nx, Bazel, or Turborepo for monorepo build tooling — they provide affected-build analysis (only build/test what changed) and remote caching for drastically faster CI.git revert triggers automatic rollback through the operator. GitOps is the recommended approach for Kubernetes deployments at any scale above a single team.🌿 Explore Git on the Interactive Mind Map
See how Git connects to CI/CD pipelines, ArgoCD GitOps, GitHub Actions, and the full DevOps toolchain.
Open Interactive Mind Map ⚙ CI/CD Guide →