7

最近gitの使用を開始しましたが、誰かが大きな(〜1.5GBファイル)をコミットすると厄介な問題が発生し、さまざまな32ビットOSでgitがクラッシュしました。これは既知のバグのようです(gitはファイルをメモリにmmapしますが、十分な予備スペースを取得できない場合は機能しません)。これはすぐには修正されません。

(私たちにとって)簡単な解決策は、gitに100MB程度を超えるコミットを拒否させることですが、それを行う方法がわかりません。

編集:問題は、大きなファイル、この場合はプログラム出力の大きなダンプの誤った送信に起因します。開発者が誤って大きなファイルを送信した場合、それをリポジトリに戻そうとするのは午後であり、誰も作業を行うことができず、すべてのローカルブランチを修正する必要があるためです。持ってる。

4

4 に答える 4

2

問題が発生したのはいつですか?彼らが最初にファイルをコミットしたとき、またはそれが他の場所にプッシュされたとき?誰もがプッシュするステージングリポジトリがある場合は、更新フックを実装して、他のアクセス許可などのチェックとともに、大きなファイルの変更された参照をスキャンできます。

非常に大まかな準備ができた例:

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) }';

(これは、Perlのワンライナーですべてを実行できることを示していますが、複数の行が必要になる場合があります;))

$ GIT_DIR / hooks / updateが呼び出される方法で呼び出されます(引数はref-name、old-rev、new-rev、たとえば「refs / heads / master master〜2 master」)。これにより、追加されたファイルが表示され、次の場合に中止されます。大きすぎるものが追加されます。

この種のことを取り締まるつもりなら、それを行うための集中化されたポイントが必要であることに注意してください。チームがお互いに変更を交換することだけを信頼している場合は、巨大なバイナリファイルを追加することは悪いことであることを学ぶためにチームを信頼する必要があります。

于 2009-05-13T16:51:35.377 に答える
2

コミットを防ぐpre-commitフックを配布できます。中央リポジトリでは、受信したデータを分析して大きなブロブを拒否し、参照されないようにする事前受信フックを設定できます。データは受信されますが、refの更新を拒否するため、受信したすべての新しいオブジェクトは参照されず、gitgcによってピックアップおよびドロップできます。

私はあなたのためのスクリプトを持っていません。

于 2009-05-13T20:45:10.613 に答える
1

コミッターのツールチェーンを制御できる場合は、「実際の」コミットの前にファイルサイズの妥当性テストを実行するようにgitcommitを変更するのが簡単な場合があります。このようなコアの変更はすべてのコミットですべてのgitユーザーに負担をかけ、「1.5GBの変更をコミットする人を追放する」という代替戦略は魅力的な単純さを持っているため、このようなテストはコアで受け入れられないのではないかと思います。gitのローカルフォーク(nannygit)を維持する負担と、野心的なコミットの後にクラッシュしたgitを修復する負担を比較検討することをお勧めします。

1.5GBのコミットがどのようになったかについて興味があることを認めなければなりません。ビデオファイルは含まれていますか?

于 2009-05-13T14:55:13.943 に答える
0
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}
于 2014-06-27T02:49:04.407 に答える