Condividi tramite


Rimuovere un file binario di grandi dimensioni dalla cronologia Git per gestire le dimensioni dei repository clonati

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022

Git è un repository di codice sorgente distribuito (repository) diffuso che consente agli utenti di lavorare con il repository completo in uno stato disconnesso. I vantaggi di Git sono ben documentati, ma cosa accade se è necessario eseguire il rollback dell'orologio nel repository primario? Questa operazione non è intuitiva e richiede autorizzazioni elevate. Questo requisito è previsto per un elemento che influisce su ogni singolo utente del repository.

Come è possibile eseguire il rollback del repository centrale in modo sicuro?

Scenario di problemi

Si supponga di eseguire il commit di un file di grandi dimensioni, ad esempio un video, nel server Git. In un sistema di codice sorgente tradizionale, è conveniente archiviare tutto in un'unica posizione e quindi tirare giù ciò che serve. Con Git, l'intero repository viene clonato nel computer locale di ogni utente. Con un file di grandi dimensioni, ogni singolo utente del progetto deve anche scaricare i file di grandi dimensioni.

Con ogni file di grandi dimensioni successivo di cui viene eseguito il commit nel server, il problema cresce solo. Il repository diventa troppo grande per essere efficiente per gli utenti. Anche se si rimuove il file di grandi dimensioni dal repository locale e si ricommette, il file esiste ancora nella cronologia del repository. Di conseguenza, il file continua a essere scaricato nel computer locale di tutti come parte della cronologia.

Screenshot che mostra la finestra di dialogo Modifiche di Team Explorer con un video di grandi dimensioni tra le modifiche incluse.

Aggiungere un file di grandi dimensioni al repository locale.

Screenshot che mostra sia i repository del server che quelli locali, entrambi con una copia dei file video di grandi dimensioni.

Dopo che hai eseguito il commit dal repository locale, anche il server possiede il file di grandi dimensioni.

Bloccare il repository

Per risolvere il problema di un repository di grandi dimensioni, è necessario iniziare dall'origine. In questo scenario, l'origine è il repository del server. Chiedi al team di interrompere il push al repository. Se si verificano più push durante questo processo, è necessario tenerne conto in modo che non si perdano dati.

Importante

La procedura seguente rimuove il video dalla cronologia dei rami, ma il file rimane nella cronologia del repository quando si clona il repository da Azure Repos. La rimozione dei file dalla cronologia del branch impedisce che i file vengano aggiornati, creando così una nuova versione del file grande nel repository.

Altre informazioni sulla gestione di file di grandi dimensioni in Git. Per una spiegazione e una soluzione alternativa per questo comportamento quando si usano i repository Git di Azure Repos, vedere Perché la clonazione da Visual Studio Team Services restituisce oggetti non referenziati obsoleti?.

Rebase e push forzato

Se nessun altro membro del team ha apportato modifiche al repository, che in genere si verificano tramite un push, è possibile prendere il percorso semplice. In pratica, il repository locale si presenta come si desidera (ovvero senza il file di grandi dimensioni). Forzare quindi le modifiche apportate al server.

Potrebbe essere necessario clonare o correggere il repository locale prima di iniziare questo lavoro. Questo processo potrebbe comportare la perdita di lavoro o modifiche, quindi procedere con cautela.

Per impostazione predefinita, è possibile modificare i file di progetto locali e eseguire il push delle modifiche nel server, ma non è possibile eseguire operazioni a livello di server come l'eliminazione o la ribasazione. Per continuare, è necessario eseguire un force push (preferibilmente) o le autorizzazioni di amministratore sul repository. Contattare l'amministratore del progetto per richiedere queste autorizzazioni o chiedere a un utente che le ha già di aiutarti. Per altre informazioni, vedere Impostare le autorizzazioni del repository Git.

Screenshot che mostra il prompt dei comandi - Git push --force permissions.

Successivamente, è necessario ribasere il repository.

  1. Usare git log per trovare i valori hash SHA (Secure Hash Algorithm) dei commit più recenti. Queste informazioni ti serviranno a breve perché devi conoscere il commit valido più recente. È possibile ottenere queste informazioni aprendo un prompt dei comandi Git e immettendo:

    git log

    In alternativa, è possibile ottenere l'hash SHA dalla visualizzazione della cronologia dei rami in Visual Studio Team Explorer.

    Screenshot che mostra l'opzione Visualizza storia del ramo principale.

  2. Aprire un prompt dei comandi Git.

    Screenshot che mostra l'azione Apri prompt dei comandi nella finestra di dialogo Sincronizzazione.

  3. Trovare il numero hash SHA di interesse.

    Screenshot che mostra il prompt dei comandi per il commit video.

    È necessario lo SHA che inizia con 25b4.

    Tenere presente che Git utilizza i puntatori per determinare dove si trova l'head o il ramo corrente nel repository. Lo stato del repository che ti interessa si trova in un certo punto del passato.

  4. Per tornare indietro nel tempo e impostare lo stato precedente sul nuovo stato corrente, usare il git rebase comando :

    git rebase -i <SHA hash of desired new current branch>

    Screenshot che mostra l'uso di rebase per rimuovere il file video.

    L'interruttore -i garantisce maggiore sicurezza perché consente di visualizzare la cronologia in un editor. Questo articolo usa un'implementazione di Git che visualizza l'editor vi classico nella riga di comando di Windows. È possibile ricordarlo se si lavora con un sistema basato su Unix.

  5. Per questo esempio, immettere:

    git rebase -i 25b4

  6. Dopo che l'editor è aperto, rimuovere tutte le righe pick ad eccezione del ramo che si vuole mantenere come nuova testa. Quando tutto sembra corretto, in vi, immettere :w\<enter\> per salvare, o immettere !q\<enter\> per uscire senza salvare.

    Screenshot che mostra il prompt dei comandi : git rebase -i comando pick 25b4.

    Modificare le righe che non si desidera più.

    Screenshot che mostra il prompt dei comandi: git rebase -i comando drop 25b4.

  7. Passare pick a drop come illustrato. Immettere :w (in vi) per salvare, quindi immettere :q! per avviare il rebase.

    Immettere git log di nuovo. Il ramo che causa l'offesa deve essere assente dal log. In caso affermativo, si è pronti per il passaggio finale, che richiede autorizzazioni di amministratore del progetto:

    git log

    Screenshot che mostra i repository locali e del server dopo il rebase.

    Il commit per il video di grandi dimensioni è ora rimosso dal repository locale.

  8. Immettere il comando seguente:

    git push --force

    Screenshot che mostra il prompt dei comandi -

    Screenshot che mostra il prompt dei comandi - risultato del comando git push --force.

    Questo comando forza il tuo repository a sovrascrivere quello sul server.

    Usare questo comando con cautela perché è possibile perdere facilmente i dati nel server.

    Screenshot che mostra un push forzato che mostra il contenuto da mantenere, senza il file video di grandi dimensioni.

Per il funzionamento di questa azione, è necessario eseguire l'autenticazione al server.

Se si usa Azure Repos, potrebbe essere necessario configurare una credenziale alternativa che non usa caratteri speciali. Un esempio è il simbolo (@) in un indirizzo di posta elettronica. Per eseguire questa attività, seguire le istruzioni riportate in Autenticazione con Azure Repos.

Ora il ramo è definitivamente rimosso dal server. I cloni e le sincronizzazioni successivi da parte dei membri del team di progetto non scaricano i file di grandi dimensioni che si sta tentando di rimuovere. Gli utenti devono eseguire il pull-down dal server per assicurarsi che siano sincronizzati con il nuovo stato del repository del server.

Se gli utenti hanno commit più recenti

Se altri utenti hanno eseguito il push dei commit nel repository del server, è necessario tenere presente un'altra considerazione. Si vuole rimuovere il ramo che contiene i file di grandi dimensioni, ma non si vogliono perdere le modifiche apportate dal team. Per risolvere questa situazione, quando apri l'editor come parte del rebase, esamina attentamente i commit. Assicurati che i commit che desideri conservare siano elencati nelle pick righe. Eliminare quelli da rimuovere, ad esempio la posizione in cui è stato aggiunto un file di grandi dimensioni.

Dopo il rebase, anche gli altri utenti del team devono eseguire il rebase in modo che tutti dispongano di una copia coerente del repository del server. Questo lavoro è noioso per tutti, e si vuole evitarlo. Se è necessario rimuovere un push, è necessario coordinarsi con il team. Per ulteriori informazioni su 'rebasing', vedere Git Branching - Rebasing.

La chiave consiste nell'assicurarsi di conoscere i commit desiderati e i commit non desiderati. Studiare git log o la cronologia nell'ambiente di sviluppo integrato (ad esempio Visual Studio). Prendere nota meticolosa degli hash SHA da mantenere e gli hash da rimuovere.

Negli scenari in cui il file di grandi dimensioni è obsoleto e sono presenti rami e merge successivi, è possibile rimuovere il file usando l'opzione git filter-branch . Per altre informazioni, vedere Rimozione di dati sensibili da un repository.

Considerazioni sulle procedure consigliate

Assicurarsi che i file di grandi dimensioni rimangano fuori dal repository principale per salvare i membri del team dal lavoro aggiuntivo. Ecco alcune procedure consigliate di buon senso che il team deve tenere presente.

Operazioni da eseguire

  • Fai commit delle modifiche frequentemente. È sempre possibile correggerli in un secondo momento con uno squash o un rebase.
  • Usare i rami per isolare le modifiche. I rami sono economici e privati e l'unione è semplice. È anche possibile eseguire il backup delle modifiche in un ramo eseguendo il push nel server.
  • Usare una convenzione di denominazione quando si pubblicano rami di argomenti. Denominare il ramo users/<alias>/<branchname>. Questo nome consente di raggruppare i rami e semplifica l'identificazione del proprietario da parte di altri utenti.
  • Ricordati di effettuare il push delle modifiche. Usare Commit != Checkin e (Commit + Push) == Checkin.
  • Prendere in considerazione l'uso .gitignore di per file binari di grandi dimensioni in modo che non vengano aggiunti al repository. Per altre informazioni, vedere Ignorare i file.
  • È consigliabile usare il controllo della versione di NuGet o Team Foundation Server per archiviare i file binari di grandi dimensioni.

Cose da evitare

  • Non ribasare dopo aver fatto un push. Il rebasing dei commit a cui è stato fatto il push in Git può essere problematico perché forza tutti gli altri utenti nel repository a fare il rebase delle loro modifiche locali. I membri del team potrebbero non essere soddisfatti se devono eseguire questa attività. La ribasazione dei commit di cui è stato eseguito il push nel proprio ramo personale, anche se eseguito il push, non è un problema a meno che altre persone non eseguano il pull di tali commit.
  • Non eseguire il commit dei file binari nel repository. Git non comprime i file binari nel modo in cui lo fa Team Foundation Version Control. Poiché tutti i repository hanno tutta la cronologia, il commit dei file binari significa ingombro permanente.

Sommario

A volte, elementi indesiderati, ad esempio file di grandi dimensioni, vengono aggiunti a un repository e devono essere rimossi per mantenere il repository pulito e leggero. È possibile eseguire questa attività sistemando il repository locale. Usare il git rebase comando e quindi usare il git push --force comando per sovrascrivere il repository del server con il repository locale.