Domanda

Abbiamo recentemente iniziato a utilizzare git e ha avuto un brutto problema quando qualcuno ha commesso un grande (~ file di 1,5 GB), che poi ha causato il crash git su vari sistemi operativi a 32 bit. Questo sembra essere un bug (mmaps git file in memoria, che non funziona se non è possibile ottenere abbastanza spazio contingous), che non sta andando per ottenere fisso in qualunque momento presto.

La soluzione facile (per noi) sarebbe quella di ottenere git di respingere ogni commit più grandi di 100 MB o giù di lì, ma non riesco a trovare un modo per farlo.

EDIT: Il problema nasce dalla presentazione accidentale di file di grandi dimensioni, in questo caso una grande discarica di output del programma. L'obiettivo è quello di evitare la presentazione accidentale, solo perché se uno sviluppatore venga accidentalmente inviare un file di grandi dimensioni, cercando di quindi ottenere di nuovo fuori il repository è un pomeriggio in cui nessuno può fare qualsiasi lavoro, e deve sistemare tutte le filiali locali hanno avere.

È stato utile?

Soluzione

Quando esattamente si verifica il problema? Quando hanno commesso il file originariamente o quando però spinto altrove? Se si dispone di un pronti contro termine messa in scena che tutti spinge a, si potrebbe implementare un gancio di aggiornamento per la scansione di arbitri che cambiano per file di grandi dimensioni, insieme ad altre autorizzazioni ecc controllo.

molto esempio rudimentale:

git --no-pager log --pretty=oneline --name-status $2..$3 -- | \
  perl -MGit -lne 'if (/^[0-9a-f]{40}/) { ($rev, $message) = split(/\s+/, $_, 2) }
     else { ($action, $file) = split(/\s+/, $_, 2); next unless $action eq "A"; 
       $filesize = Git::command_oneline("cat-file", "-s", "$rev:$file");
       print "$rev added $file ($filesize bytes)"; die "$file too big" if ($filesize > 1024*1024*1024) }';

(va solo a dimostrare, tutto può essere fatto con un Perl one-liner, anche se potrebbe richiedere più linee;))

Chiamato nel modo in cui $ GIT_DIR / ganci / aggiornamento viene chiamato (args sono ref-name, old-rev, new-rev; ad esempio, "refs / teste / Master ~ 2 master") questo mostrerà i file aggiunti e abortire se ne è aggiunto uno che è troppo grande.

Si noti che direi che se avete intenzione di sorvegliare questo genere di cose, è necessario un punto centralizzato in cui farlo. Se vi fidate la vostra squadra per scambiare solo i cambiamenti con l'altro, si dovrebbe fidarsi di loro per imparare che l'aggiunta di giganti file binari è una brutta cosa.

Altri suggerimenti

È possibile distribuire un pre-commit hook che impedisce commit. Su repository centrale si può avere un pre-ricezione gancio che rifiuta grandi blob analizzando i dati ricevuti e impedire che venga fatto riferimento. saranno ricevuti i dati, ma dal momento che si rifiuta aggiornamenti di arbitri, tutti i nuovi oggetti ricevuti sarà senza riferimenti e possono essere prelevati e riaccompagnati da git gc.

Non ho uno script per voi però.

Se si ha il controllo toolchain tuoi committer, può essere semplice per modificare git commit in modo che esegue un test di ragionevolezza sulla dimensione del file prima della 'vera' commit. Dal momento che un tale cambiamento nel nucleo avrebbero onere tutti gli utenti git su ogni impegno, e la strategia alternativa di "bandire tutti coloro che commettere un cambiamento 1.5GB" ha una semplicità accattivante, ho il sospetto che una tale prova non sarà mai accettata nel nucleo. Vi suggerisco di pesare l'onere di mantenere una forchetta locale git - nannygit -. Contro l'onere della riparazione di un git si è schiantato in seguito a un troppo ambizioso commit

Devo ammettere che sono curioso di sapere come un 1,5 GB commit venuto essere. Sono coinvolti i file video?

Here is my solution. I must admit it doesn't look like others I have seen, but to me it makes the most sense. It only checks the inbound commit. It does detect when a new file is too large, or an existing file becomes too big. It is a pre-receive hook. Since tags are size 0, it does not check them.

    #!/usr/bin/env bash
#
# This script is run after receive-pack has accepted a pack and the
# repository has been updated.  It is passed arguments in through stdin
# in the form
#  <oldrev> <newrev> <refname>
# For example:
#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
#
# see contrib/hooks/ for an sample, or uncomment the next line (on debian)
#

set -e

let max=1024*1024
count=0
echo "Checking file sizes..."
while read oldrev newrev refname
do
#   echo $oldrev $newrev $refname
    # skip the size check for tag refs
    if [[ ${refname} =~ ^refs/tags/* ]]
    then
        continue
    fi

    if [[ ${newrev} =~ ^[0]+$ ]]
    then
        continue
    fi

    # find all refs we don't care about and exclude them from diff
    if [[ ! ${oldrev} =~ ^[0]+$ ]]
    then
        excludes=^${oldrev}
    else
        excludes=( $(git for-each-ref --format '^%(refname:short)' refs/heads/) )
    fi
#   echo "excludes " ${excludes}
    commits=$(git rev-list $newrev "${excludes[@]}")
    for commit in ${commits};
    do
#       echo "commit " ${commit}
        # get a list of the file changes in this commit
        rawdiff=$(git diff-tree --no-commit-id ${commit})
        while read oldmode newmode oldsha newsha code fname
        do
#           echo "reading " ${oldmode} ${newmode} ${oldsha} ${newsha} ${code} ${fname}
            # if diff-tree returns anything, new sha is not all 0's, and it is a file (blob)
            if [[ "${newsha}" != "" ]] && [[ ! ${newsha} =~ ^[0]+$ ]] && [[ $(git cat-file -t ${newsha}) == "blob" ]]
            then
                echo -n "${fname} "
                newsize=$(git cat-file -s ${newsha})
                if (( ${newsize} > ${max} ))
                then
                    echo " size ${newsize}B > ${max}B"
                    let "count+=1"
                else
                    echo "ok"
                fi
            fi
        done <<< "${rawdiff}"
    done
done

exit ${count}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top