← AZ-400: DevOps da entrega à operação
16 / 26 · 100 MIN

Repositórios: conteúdo, escala e recuperação coordenada

Distingue referências de bytes disponíveis, otimiza o working tree e planeia alterações ao histórico com rastreabilidade e recuperação.

1. Identificar o conteúdo que o build realmente precisa

Uma equipa fictícia prepara a recuperação de uma aplicação de processamento de fundos. O código foi obtido do commit aprovado, mas uma ferramenta falha ao abrir rules.bin. O ficheiro contém texto com a versão do formato LFS, um identificador do objeto e o tamanho esperado. Isto não demonstra corrupção do código: pode ser apenas um ponteiro que ainda não foi substituído pelo conteúdo. Git LFS conserva referências no repositório e guarda os bytes separadamente. Começa por identificar que input é necessário, qual referência o seleciona e onde esses bytes devem estar disponíveis. Não uses o URL do formato como endereço de download. Decide também onde cada tipo de conteúdo pertence: código e regras editáveis no repositório; dependências versionadas num mecanismo de pacotes; outputs de build num armazenamento de artefactos. LFS não é uma razão para guardar todos os outputs em Git.

2. Partilhar regras sem confundir configuração e migração

Um comando git lfs track acrescenta regras a .gitattributes. Revê e versiona esse ficheiro para novos clones receberem a intenção do projeto. Se apenas uma máquina tiver regras locais, o comportamento dos colaboradores pode divergir. Adicionar regras agora não transforma automaticamente todos os binários já presentes em commits antigos. Uma migração do histórico é outra mudança, com âmbito próprio. O manual de git lfs migrate distingue modos de análise, importação e exportação; os modos que reescrevem histórico alteram identificadores, com uma exceção específica para importação sem reescrita. Não assumes que a invocação por omissão cobre todas as branches remotas. Antes de propor uma migração, inventaria as referências e tipos de ficheiro relevantes, preserva trabalho local e ensaia num ambiente isolado. A publicação do histórico alterado precisa de coordenação com quem mantém pipelines, tags, PRs e cópias de trabalho.

3. Obter um objeto e escrevê-lo no working tree são passos diferentes

No exercício de build, confirma se existe cliente LFS, se a obtenção do objeto foi concluída e se o working tree contém o binário esperado. git lfs fetch descarrega objetos, mas não atualiza o working tree. git lfs checkout usa objetos disponíveis localmente para materializar caminhos elegíveis; não faz o download. Um fetch bem-sucedido pode, por isso, coexistir com um ponteiro ainda presente. O checkout também preserva ficheiros modificados, pelo que não deves prometer uma substituição indiscriminada. Investiga o estado local antes de repetir comandos. Se o objeto está ausente, resolve a sua obtenção através da origem autorizada. Se existe, verifica porque não foi materializado no caminho usado pelo build. Uma cópia do portátil de alguém só é uma alternativa aceitável quando a versão e a integridade correspondem ao input exigido e o procedimento permite essa origem. Confirma ainda que o caminho está no índice e que as regras LFS relevantes estão disponíveis ao cliente.

4. Definir o que um arquivo ou backup consegue reconstruir

Um ZIP de código fonte gerado pelo GitHub não deve ser tratado como prova automática de completude dos inputs. Por omissão, os arquivos contêm os ponteiros LFS. Existe uma opção para incluir objetos abrangidos pelas regras versionadas, mas os de um servidor LFS externo não são incluídos por essa opção. Distingue também estes arquivos gerados de um pacote de release preparado e carregado pela equipa. Para backup, parte das releases que prometes recuperar. As referências Git e os objetos LFS associados precisam de estar disponíveis no material conservado. Se só obtiveste os objetos do HEAD atual, não demonstraste recuperação de versões antigas. O ensaio deve reconstruir as referências acordadas, confirmar conteúdo e detetar dependências silenciosas do servidor de origem. Regista explicitamente qualquer lacuna, em vez de declarar sucesso apenas porque o clone terminou sem erro.

5. Usar sparse checkout como seleção local, com limites claros

O monorepo do laboratório tem duas aplicações e um runbook operacional. Selecionar services/payments em cone mode mantém essa subárvore e também ficheiros imediatamente nos diretórios ancestrais, como README.md na raiz e services/README.md. A ausência de services/funds no working tree não representa uma eliminação do commit. O exercício confirma isso com git show e verifica que uma alteração à documentação visível não apaga os ficheiros excluídos. Depois acrescenta ops à seleção e, por fim, desativa sparse checkout para repor todos os caminhos. Este comportamento ajuda a reduzir o conjunto de trabalho, mas não implementa confidencialidade. Um prestador com acesso ao repositório não perde acesso aos objetos porque a sua pasta local mostra menos ficheiros. Se há uma separação obrigatória de acesso, desenha e valida uma fronteira de autorização apropriada à plataforma e à organização.

6. Otimizar a dimensão certa e conservar evidência de release

Sparse checkout, partial clone e clone raso tratam problemas diferentes. O primeiro seleciona caminhos no working tree; um filtro como blob:none adia conteúdo de ficheiros; depth limita a história de commits obtida. Se a análise precisa de commits antigos, reduzir depth pode remover precisamente a informação necessária. Se adias blobs, operações posteriores podem depender de nova obtenção, pelo que não deves prometer trabalho offline completo. Mede o efeito no fluxo real, incluindo testes que precisam de outra pasta. Considera ainda as tags: um clone com no-tags conserva essa opção na configuração para fetch posteriores, embora continue a permitir obtenção explícita de tags. Uma pipeline que não encontra a tag aprovada deve distinguir ausência local por configuração de ausência no remoto. Criar uma tag nova no HEAD apenas para fazer o script passar não recupera a referência aprovada.

7. Coordenar mudanças que alteram o significado das referências

Uma tag já usada por QA e RUN representa um acordo sobre uma versão. Movê-la silenciosamente pode deixar consumidores com o mesmo nome e objetos diferentes. Quando o processo o permite, publica uma nova referência e comunica a correção. Numa limpeza de histórico, identifica clones antigos e PRs que podem ser afetados ou reintroduzir conteúdo. Se o motivo é uma credencial exposta, revogação ou rotação vem primeiro; remover texto do histórico não substitui essa resposta. Distingue também capacidades administrativas: Contribute, Edit policies, bypass e Force push não são sinónimos em Azure Repos. Criar uma branch não concede automaticamente edição de políticas no comportamento atual documentado. O responsável deve analisar grupos, herança e permissões efetivas, concedendo apenas o âmbito aprovado. A capacidade técnica de executar uma mudança não demonstra que a coordenação e os critérios de recuperação estejam prontos.

8. Ensaiar e entregar um procedimento verificável a RUN

Executa o laboratório Python: cria um repositório temporário, desativa hooks e assinaturas, não configura remotos e limpa os ficheiros no fim. Antes de cada assert, prevê quais caminhos aparecem e se continuam no commit. As 17 verificações cobrem cone mode, leitura de um caminho excluído, preservação da árvore e reposição do working tree. Não cobrem LFS, autorização remota nem desempenho. Para o caso rules.bin, escreve um runbook separado com referência aprovada, origem do objeto, verificação dos inputs, decisão perante objeto ausente e responsável pela exceção. No handover, pede a outro operador que explique como distinguir clone concluído, objeto obtido, conteúdo materializado e build aceite. São observações diferentes. O resumo é preservar identidade e disponibilidade do conteúdo, otimizar sem perder o contexto necessário e coordenar qualquer mudança que afete as referências usadas por outras equipas.

# 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','dr.pt 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.'}))
NA PRÁTICA

Um agente de recuperação tem o commit aprovado, mas rules.bin ainda é um ponteiro LFS. O caso exige obter o objeto certo e provar os inputs antes de repetir o build.

Armadilhas comuns

Aceitar um ponteiro como binário; confundir fetch com checkout; tratar sparse checkout como permissão; alterar tags publicadas sem coordenação; validar backups apenas pelo clone Git.

Tópicos relacionados: Proveniência de artefactos · Configuração de agentes CI · Permissões e gestão de mudanças · Backups e recuperação de aplicações

Leva esta ideia contigo

A referência aprovada tem de conduzir a bytes disponíveis e identificados. Otimiza caminhos, objetos e história de forma consciente e verifica recuperação antes de prometer continuidade.

Criar conta

Referência: About Git Large File Storage · AZ-400 objectives 2026-07-27

Microsoft é uma marca comercial do grupo de empresas Microsoft. A dr.pt é uma plataforma de preparação independente e não está afiliada, associada, patrocinada, autorizada nem aprovada por Microsoft. Os conteúdos e as perguntas são originais, não são perguntas oficiais de exame, e concluir os nossos testes não atribui nem garante qualquer certificação. Os nomes são usados apenas para identificar o tema. Todas as outras marcas pertencem aos respetivos titulares.