Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to limit file size on commit?

Is there an option to limit the file size when committing?

For example: file sizes above 500K would produce a warning. File sizes above 10M would stop the commit.

I'm fully aware of this question which technically makes this a duplicate but the answers only offer a solution on push, which would be too late for my requirements.

like image 548
Yuval Atzmon Avatar asked Sep 19 '16 14:09

Yuval Atzmon


People also ask

What is the maximum file size for a single commit?

There is no limit on the number or the total size of all files in a single commit, as long as the data does not exceed 20 MB, an individual file does not exceed 6 MB, and a single blob does not exceed 2 GB.

Is there a way to check file size before a commit?

There is a general pre-commit hook. You can write a script to check file size and then accept or reject the commit. Git however gives the user the ability to bypass the check) from the command line type "git help hooks" for more information. Here is the relevant info on the pre-commit hook.

What is the maximum file size for a codecommit repository?

When specifying the path to a file in a CodeCommit repository, use the standards for Amazon Linux. Maximum of 6 MB for any individual file when using the CodeCommit console, APIs, or the AWS CLI. Maximum of 2 GB.

What is the size limit for the error cannot commit Foo?

Error: Cannot commit 'foo' because it is 117.9MB, which exceeds the hard size limit of 10.0MB. What is improved about it? Clarified in the description. It isn't inherently better, just shorter and simpler, with more a human-friendly display of file sizes.


2 Answers

This pre-commit hook will do the file size check:

.git/hooks/pre-commit

#!/bin/sh
hard_limit=$(git config hooks.filesizehardlimit)
soft_limit=$(git config hooks.filesizesoftlimit)
: ${hard_limit:=10000000}
: ${soft_limit:=500000}

list_new_or_modified_files()
{
    git diff --staged --name-status|sed -e '/^D/ d; /^D/! s/.\s\+//'
}

unmunge()
{
    local result="${1#\"}"
    result="${result%\"}"
    env echo -e "$result"
}

check_file_size()
{
    n=0
    while read -r munged_filename
    do
        f="$(unmunge "$munged_filename")"
        h=$(git ls-files -s "$f"|cut -d' ' -f 2)
        s=$(git cat-file -s "$h")
        if [ "$s" -gt $hard_limit ]
        then
            env echo -E 1>&2 "ERROR: hard size limit ($hard_limit) exceeded: $munged_filename ($s)"
            n=$((n+1))
        elif [ "$s" -gt $soft_limit ]
        then
            env echo -E 1>&2 "WARNING: soft size limit ($soft_limit) exceeded: $munged_filename ($s)"
        fi
    done

    [ $n -eq 0 ]
}

list_new_or_modified_files | check_file_size

Above script must be saved as .git/hooks/pre-commit with execution permissions enabled (chmod +x .git/hooks/pre-commit).

The default soft (warning) and hard (error) size limits are set to 500,000 and 10,000,000 bytes but can be overriden through the hooks.filesizesoftlimit and hooks.filesizehardlimit settings respectively:

$ git config hooks.filesizesoftlimit 100000
$ git config hooks.filesizehardlimit 4000000
like image 172
Leon Avatar answered Sep 17 '22 07:09

Leon


A shorter, bash-specific version of @Leon's script, which prints the file sizes in a human-readable format. It requires a newer git for the --diff-filter=d option:

#!/bin/bash
hard_limit=$(git config hooks.filesizehardlimit)
soft_limit=$(git config hooks.filesizesoftlimit)
: ${hard_limit:=10000000}
: ${soft_limit:=1000000}

status=0

bytesToHuman() {
  b=${1:-0}; d=''; s=0; S=({,K,M,G,T,P,E,Z,Y}B)
  while ((b > 1000)); do
    d="$(printf ".%01d" $((b % 1000 * 10 / 1000)))"
    b=$((b / 1000))
    let s++
  done
  echo "$b$d${S[$s]}"
}

# Iterate over the zero-delimited list of staged files.
while IFS= read -r -d '' file ; do
  hash=$(git ls-files -s "$file" | cut -d ' ' -f 2)
  size=$(git cat-file -s "$hash")

  if (( $size > $hard_limit )); then
    echo "Error: Cannot commit '$file' because it is $(bytesToHuman $size), which exceeds the hard size limit of $(bytesToHuman $hard_limit)."
    status=1
  elif (( $size > $soft_limit )); then
    echo "Warning: '$file' is $(bytesToHuman $size), which exceeds the soft size limit of $(bytesToHuman $soft_limit). Please double check that you intended to commit this file."
  fi
done < <(git diff -z --staged --name-only --diff-filter=d)
exit $status

As with the other answers, this must be saved with execute permissions as .git/hooks/pre-commit.

Example output:

Error: Cannot commit 'foo' because it is 117.9MB, which exceeds the hard size limit of 10.0MB.
like image 35
Connor McKay Avatar answered Sep 19 '22 07:09

Connor McKay