2.1.5.1. Git Operations, Permissions, and Recovery
2.1.5.1. Git Operations, Permissions, and Recovery
Git repository management goes beyond basic commit/push workflows. Understanding reference logs (git reflog) enables recovery from seemingly catastrophic mistakes — every HEAD movement is recorded for 90 days, allowing you to resurrect deleted branches or undo bad rebases. git rm --cached removes files from tracking without deleting them from disk, essential when sensitive files were accidentally committed. Branch policies and protections enforce workflow discipline at the server level, preventing force-pushes to protected branches and requiring PR-based workflows. Fine-grained permissions in Azure Repos allow path-level security — restricting database migration files to the DBA team while giving everyone read access. Credential scanning should happen pre-commit (before secrets enter history) rather than only in CI, because Git history is permanent.
Advanced Git operations become critical when recovering from mistakes or managing complex histories. Interactive rebase (git rebase -i) rewrites commit history — squashing, reordering, or editing commits before pushing. This creates clean, logical commit sequences for review while preserving the messy development process locally.
Cherry-picking (git cherry-pick <sha>) applies a specific commit from one branch to another — essential for hotfix workflows where a fix needs to land on both main and a release branch without merging the entire branch. Bisect (git bisect) performs binary search through commit history to find which commit introduced a bug, reducing a 500-commit search space to ~9 checks.
Submodules embed one Git repository inside another — useful for shared libraries but notoriously painful for CI configuration and developer workflow. Subtree merges provide a simpler alternative at the cost of duplicated history. Azure Repos supports both, but subtrees are generally preferred for their simplicity in CI pipelines.
Git hooks provide local automation at key points in the development workflow. Pre-commit hooks run before git commit — ideal for linting, formatting, and credential scanning. Pre-push hooks run before git push — suitable for running fast test suites. Commit-msg hooks validate commit message format (conventional commits for automated changelogs).
Server-side hooks in Azure Repos provide enforcement that client-side hooks cannot: prevent force-pushes to protected branches, require minimum commit message length, and block pushes containing files over a size threshold. Unlike client-side hooks (which developers can bypass), server-side hooks are authoritative.
Sparse checkout with cone mode restricts the working directory to specific top-level directories, dramatically reducing disk usage and checkout time for developers working on one service in a large monorepo. Combined with partial clone (--filter=blob:none), developers get instant repository access with blobs downloaded on demand as they navigate into directories.
Repository size management becomes critical at scale. Azure DevOps supports partial clone (filter out large files during clone) and sparse checkout (retrieve only specific directories). For monorepos, these features reduce clone time from minutes to seconds by fetching only the paths relevant to each developer's work.
Git hooks provide client-side automation: pre-commit hooks run linters, commit-msg hooks enforce message formats, and pre-push hooks run quick tests before uploading.
Cherry-picking commits between branches with git cherry-pick enables targeted hotfix application without merging entire branches.