← AZ-400: DevOps from delivery to operations
16 / 26 · 100 MIN

Repositories: content, scale and coordinated recovery

Distinguish references from available bytes, optimize the working tree and plan history changes with traceability and recovery.

1. Identify the content the build actually needs

A fictional team prepares recovery of a funds-processing application. Code comes from the approved commit, but a tool fails when opening rules.bin. The file contains text identifying the LFS format, an object identifier and expected size. This does not establish source corruption: it can be a pointer that has not yet been replaced with content. Git LFS keeps references in the repository and stores bytes separately. Start by identifying the required input, the reference selecting it and where those bytes should be available. Do not use the format URL as a download address. Also decide where each content type belongs: code and editable rules in the repository; versioned dependencies in package management; build outputs in artifact storage. LFS is not a reason to place every build output in Git.

2. Share rules without confusing configuration and migration

A git lfs track command adds rules to.gitattributes. Review and commit that file so new clones receive the project’s intent. If only one machine has local rules, collaborators can behave differently. Adding rules now does not automatically transform every binary already present in old commits. History migration is a separate change with its own scope. The git lfs migrate manual distinguishes information, import and export modes; history-rewriting modes change identifiers, with a specific exception for no-rewrite import. Do not assume a default invocation covers every remote branch. Before proposing migration, inventory relevant refs and file types, preserve local work and rehearse in isolation. Publishing changed history requires coordination with people maintaining pipelines, tags, pull requests and working copies. Treat success as a validated result over an agreed scope rather than a successful command alone.

3. Retrieving an object and writing it into the working tree are different steps

In the build exercise, check whether an LFS client exists, object retrieval completed and the working tree contains the expected binary. git lfs fetch downloads objects but does not update the working tree. git lfs checkout uses locally available objects to materialize eligible paths; it does not download them. A successful fetch can therefore coexist with a pointer still being present. Checkout also preserves modified files, so do not promise indiscriminate replacement. Inspect local state before repeating commands. If an object is missing, address retrieval through the authorized source. If it exists, establish why it was not materialized at the path the build uses. A copy from someone’s laptop is an acceptable alternative only when version and integrity match the required input and the procedure permits that source. Also confirm the path is in the index and the relevant LFS attribute rules are available to the client.

4. Define what an archive or backup can reconstruct

A source ZIP generated by GitHub should not be treated as automatic proof of complete inputs. By default, archives contain LFS pointers. An option can include objects covered by committed tracking rules, but objects on an external LFS server are not included through that option. Also distinguish these generated archives from a release package prepared and uploaded by the team. For backup, start with the releases you promise to recover. Git refs and associated LFS objects need to be available in retained material. If you only retrieved current-HEAD objects, you have not established recovery of older versions. The exercise should reconstruct agreed refs, confirm content and detect silent dependencies on the original server. Explicitly record any gap rather than declaring success merely because cloning finished without an error.

5. Use sparse checkout as local selection with clear limits

The lab monorepo has two applications and an operational runbook. Selecting services/payments in cone mode retains that subtree and files immediately inside ancestor directories, such as root README.md and services/README.md. Absence of services/funds from the working tree does not represent deletion from the commit. The exercise establishes this with git show and checks that changing visible documentation does not delete excluded files. It then adds ops to selection and finally disables sparse checkout to restore every path. This behavior helps reduce the working set but does not implement confidentiality. A contractor with repository access does not lose object access because their local directory shows fewer files. Where mandatory access separation exists, design and validate an authorization boundary appropriate to the platform and organization instead of relying on a local display choice.

6. Optimize the right dimension and retain release evidence

Sparse checkout, partial clone and shallow clone address different problems. The first selects working-tree paths; a filter such as blob:none defers file content; depth limits retrieved commit history. If analysis needs old commits, reducing depth can remove precisely the required information. If blobs are deferred, later operations can depend on further retrieval, so do not promise complete offline work. Measure the effect on the real workflow, including tests needing another directory. Also consider tags: cloning with no-tags preserves that option in configuration for later fetches, although explicit tag retrieval remains possible. A pipeline unable to find an approved tag should distinguish local absence caused by configuration from absence on the remote. Creating a new tag at HEAD just to make a script pass does not recover the approved reference.

7. Coordinate changes that alter reference meaning

A tag already used by QA and RUN represents agreement about a version. Moving it silently can leave consumers with the same name and different objects. Where the process permits, publish a new reference and communicate the correction. For history cleanup, identify old clones and pull requests that may be affected or reintroduce content. If an exposed credential prompted the work, revocation or rotation comes first; removing history text does not replace that response. Also distinguish administrative capabilities: Contribute, Edit policies, bypass and Force push are not synonyms in Azure Repos. Creating a branch does not automatically grant policy editing under current documented behavior. The access owner should inspect groups, inheritance and effective permissions, granting only approved scope. Technical ability to execute a change does not establish that coordination and recovery criteria are ready.

8. Rehearse and hand RUN a verifiable procedure

Run the Python lab: it creates a temporary repository, disables hooks and signing, configures no remotes and cleans files afterwards. Before each assertion, predict which paths appear and whether they remain in the commit. Its 17 checks cover cone mode, reading an excluded path, preserving the tree and restoring the working tree. They do not cover LFS, remote authorization or performance. For the rules.bin case, write a separate runbook with approved ref, object source, input verification, a decision for missing objects and exception ownership. During handover, ask another operator to explain how to distinguish completed clone, retrieved object, materialized content and accepted build. These are different observations. The summary is to preserve content identity and availability, optimize without losing necessary context and coordinate changes affecting refs that other teams consume.

# Original isolated Git exercise: all writes are inside a new temporary directory.
# It checks sparse working-tree behavior, not authorization, LFS servers or partial clones.
from pathlib import Path
import subprocess, tempfile, os, json
with tempfile.TemporaryDirectory(prefix='dr-az400-sparse-') as temp:
 base=Path(temp); repo=base/'repo' repo.mkdir; hooks=base/'empty-hooks' hooks.mkdir
 env={'PATH':os.environ['PATH'],'GIT_CONFIG_NOSYSTEM':'1','GIT_CONFIG_GLOBAL':'/dev/null','GIT_TERMINAL_PROMPT':'0','GIT_ALLOW_PROTOCOL':'file','LC_ALL':'C'}
 def git(*args):
 p=subprocess.run(['git','-c',f'core.hooksPath={hooks}','-c','commit.gpgsign=false','-c','tag.gpgsign=false',*args],cwd=repo,env=env,text=True,capture_output=True,check=True)
 return p.stdout.strip
 version=git('--version')
 git('init','-b','main');git('config','user.name','BigSavant fictional lab');git('config','user.email','lab@example.invalid')
 files={'README.md':'Repository overview\n','services/README.md':'Service conventions\n','services/payments/app.txt':'payments version one\n','services/payments/config.txt':'fictional=true\n','services/funds/app.txt':'funds version one\n','ops/runbook.txt':'Restore using an approved artifact\n'}
 for name,body in files.items:
 p=repo/name;p.parent.mkdir(parents=True,exist_ok=True);p.write_text(body)
 git('add','.');git('commit','-m','Add fictional fixture')
 original=git('rev-parse','HEAD')
 git('sparse-checkout','set','--cone','services/payments')
 assert (repo/'README.md').exists
 assert (repo/'services/README.md').exists
 assert (repo/'services/payments/app.txt').exists
 assert not (repo/'services/funds/app.txt').exists
 assert not (repo/'ops/runbook.txt').exists
 assert git('show','HEAD:ops/runbook.txt')==files['ops/runbook.txt'].strip
 assert git('status','--porcelain')==''
 assert git('rev-parse','HEAD')==original
 assert git('sparse-checkout','list')=='services/payments'
 assert len(git('ls-tree','-r','--name-only','HEAD').splitlines)==6
 (repo/'README.md').write_text(files['README.md']+'A documentation update\n')
 git('add','README.md');git('commit','-m','Update visible documentation')
 assert git('show','HEAD:ops/runbook.txt')==files['ops/runbook.txt'].strip
 assert len(git('ls-tree','-r','--name-only','HEAD').splitlines)==6
 git('sparse-checkout','add','ops')
 assert (repo/'ops/runbook.txt').exists
 assert not (repo/'services/funds/app.txt').exists
 git('sparse-checkout','disable')
 assert all((repo/name).exists for name in files)
 assert git('remote')==''
 assert git('status','--porcelain')==''
 print(json.dumps({'assertions':17,'passed':True,'gitVersion':version,'scope':'Temporary local repository, no remotes, hooks disabled, no credentials or network. Sparse checkout only; not an access-control test.'}))
IN PRACTICE

A recovery agent has the approved commit, but rules.bin remains an LFS pointer. The case requires retrieving the correct object and establishing inputs before retrying the build.

Common pitfalls

Accepting a pointer as a binary; confusing fetch with checkout; treating sparse checkout as permission; changing published tags without coordination; validating backups only by Git cloning.

Related topics: Artifact provenance · CI agent configuration · Permissions and change management · Application backup and recovery

Take this idea with you

The approved reference must lead to available, identified bytes. Optimize paths, objects and history deliberately and verify recovery before promising continuity.

Create account

Reference: About Git Large File Storage · AZ-400 objectives 2026-07-27

Microsoft is a trademark of the Microsoft group of companies. bigsavant.com is an independent preparation platform and is not affiliated with, associated with, sponsored, authorised or endorsed by Microsoft. Content and questions are original, are not official exam questions, and completing our tests does not award or guarantee any certification. Names are used only to identify the subject. All other trademarks belong to their respective owners.