2011-08-22 19 views
21

Actualmente estoy pensando en cambiar mi VCS (de subversión) a git. ¿Es posible limitar el tamaño del archivo dentro de un commit en un repositorio de git? Delantero. gramo. subversion hay un gancho: http://www.davidgrant.ca/limit_size_of_subversion_commits_with_this_hookLimitar el tamaño del archivo en el repositorio de git

Según mi experiencia, las personas, especialmente las que no tienen experiencia, a veces tienden a enviar archivos que no deberían entrar en un VCS (por ejemplo, imágenes de un sistema de archivos grandes).

Respuesta

2

Sí, git tiene ganchos también (git hooks). Pero depende de la corriente de trabajo que usará.

Si tiene usuarios inexpertos, es mucho más seguro tirar, luego dejarlos presionar. De esta forma, puedes asegurarte de que no arruinen el repositorio principal.

2

Puede usar un hook, ya sea pre-commit gancho (en el cliente), o un gancho update (en el servidor). Realice un git ls-files --cached (para precompromiso) o git ls-tree --full-tree -r -l $3 (para actualizar) y actúe en consecuencia.

git ls-tree -l daría algo como esto:

100644 blob 97293e358a9870ac4ddf1daf44b10e10e8273d57 3301 file1 
100644 blob 02937b0e158ff8d3895c6e93ebf0cbc37d81cac1  507 file2 

Grab la cuarta columna, y es el tamaño. Use git ls-tree --full-tree -r -l HEAD | sort -k 4 -n -r | head -1 para obtener el archivo más grande. cut para extraer, if [ a -lt b ] para verificar el tamaño, etc.

Lo siento, creo que si eres un programador, deberías poder hacerlo tú mismo.

+10

Downvoted for bullsh ** hágalo usted mismo. –

+0

@ J-16SDiZ Respuesta muy inmadura. – nash

0

Otra forma es la versión .gitignore, que evitará que cualquier archivo con una cierta extensión se muestre en el estado.
Usted todavía puede tener ganchos también (en sentido ascendente o descendente, según lo sugerido por las otras respuestas), pero al menos todos repo aguas abajo puede incluir que .gitignore para evitar la adición de .exe, .dll, .iso, ...

+0

Nota: los ganchos no se propagan a través del clon: http://stackoverflow.com/questions/5165239/why-it-is-not-possible-to-git-add-git-hooks-my-hook/5165299#5165299) – VonC

0

Este va a ser un caso muy raro de lo que he visto cuando alguien ingresa, digamos un archivo de tamaño de 200Mb o incluso más.

Si bien puede evitar que esto suceda mediante el uso de ganchos del lado del servidor (no estoy seguro de los ganchos del lado del cliente ya que tiene que confiar en la persona que tiene los ganchos instalados) como SVN, también debe tener en cuenta que en Git, es mucho más fácil eliminar dicho archivo/confirmación del repositorio. No tenías tanto lujo en SVN, al menos no es una manera fácil.

+0

En realidad, en git no es más difícil? Un 'git rm' del archivo en realidad no lo elimina del repositorio, simplemente hace que no aparezca en las revisiones posteriores. Aún desperdicia el espacio/ancho de banda para ello. –

+0

@JosephGarvin - ¿Cómo? 'git rm' es el comando para eliminar un archivo de la confirmación actual. No cambia la historia. Usted tiene otros comandos como 'git commit --amend' y' git filter-branch' – manojlds

19

Como estuve luchando con esto por un tiempo, incluso con la descripción, y creo que esto también es relevante para otros, pensé en publicar una implementación de cómo podría implementarse J16 SDiZ described.

Por lo tanto, mi opinión sobre el gancho del lado del servidor update prevención de archivos demasiado grandes para ser empujado:

#!/bin/bash 

# Script to limit the size of a push to git repository. 
# Git repo has issues with big pushes, and we shouldn't have a real need for those 
# 
# eis/02.02.2012 

# --- Safety check, should not be run from command line 
if [ -z "$GIT_DIR" ]; then 
     echo "Don't run this script from the command line." >&2 
     echo " (if you want, you could supply GIT_DIR then run" >&2 
     echo " $0 <ref> <oldrev> <newrev>)" >&2 
     exit 1 
fi 

# Test that tab replacement works, issue in some Solaris envs at least 
testvariable=`echo -e "\t" | sed 's/\s//'` 
if [ "$testvariable" != "" ]; then 
     echo "Environment check failed - please contact git hosting." >&2 
     exit 1 
fi 


# File size limit is meant to be configured through 'hooks.filesizelimit' setting 
filesizelimit=$(git config hooks.filesizelimit) 

# If we haven't configured a file size limit, use default value of about 100M 
if [ -z "$filesizelimit" ]; then 
     filesizelimit=100000000 
fi 

# Reference to incoming checkin can be found at $3 
refname=$3 

# With this command, we can find information about the file coming in that has biggest size 
# We also normalize the line for excess whitespace 
biggest_checkin_normalized=$(git ls-tree --full-tree -r -l $refname | sort -k 4 -n -r | head -1 | sed 's/^ *//;s/ *$//;s/\s\{1,\}/ /g') 

# Based on that, we can find what we are interested about 
filesize=`echo $biggest_checkin_normalized | cut -d ' ' -f4,4` 

# Actual comparison 
# To cancel a push, we exit with status code 1 
# It is also a good idea to print out some info about the cause of rejection 
if [ $filesize -gt $filesizelimit ]; then 

     # To be more user-friendly, we also look up the name of the offending file 
     filename=`echo $biggest_checkin_normalized | cut -d ' ' -f5,5` 

     echo "Error: Too large push attempted." >&2 
     echo >&2 
     echo "File size limit is $filesizelimit, and you tried to push file named $filename of size $filesize." >&2 
     echo "Contact configuration team if you really need to do this." >&2 
     exit 1 
fi 

exit 0 
+0

¿Cómo usarlo? ¿Ejecutar este archivo cada vez antes de comprometer? – Gank

+0

@Gank ¿leyó la respuesta a la que me he vinculado? – eis

+0

Sí. Pero no sé cómo configurarlo en git. – Gank

0

estoy usando gitolite y ya estaba siendo utilizado el gancho de actualización - en lugar de usar el gancho de actualización, Usé el gancho de pre-recepción.El guión Publicado por Chriki trabajó fabulosamente con la excepción de que los datos se pasan a través de la entrada estándar - por lo que hizo un cambio de línea:

- refname=$3 
+ read a b refname 

(puede haber una forma más elegante de hacer eso, pero funciona)

4

si está usando gitolite también puede probar VREF. Hay un VREF ya proporcionado por defecto (el código está en gitolite/src/VREF/MAX_NEWBIN_SIZE). Se llama MAX_NEWBIN_SIZE. Funciona así:

repo name 
RW+  = username 
- VREF/MAX_NEWBIN_SIZE/1000 = usernames 

Donde 1000 es ejemplo de umbral en bytes.

Este VREF funciona como un gancho de actualización y rechazará su inserción si un archivo que va a presionar es mayor que el umbral.

6

Las respuestas de eis y J-16 SDiZ adolecen de un grave problema. Solo están verificando el estado de la confirmación final $ 3 o $ newrev. También deben verificar lo que se envía en las otras confirmaciones entre $ 2 (o $ oldrev) y $ 3 (o $ newrev) en el gancho de udpate.

J-16 SDiZ está más cerca de la respuesta correcta.

El gran defecto es que alguien cuya departamental servidor ha instalado esta actualización de gancho para protegerlo encontrará la manera dura que:

Después de usar git rm para eliminar el archivo grande accidentalmente registró, entonces el el árbol actual o el último compromiso solo estarán bien, y se eliminará toda la cadena de confirmaciones, incluido el archivo grande que se borró, creando un historial de grasa inflado e hinchado que nadie quiere.

La solución consiste en verificar cada confirmación de $ oldrev a $ newrev, o bien especificar el rango completo $ oldrev .. $ newrev. Sea maldito seguro de que no solo está comprobando $ newrev solo, o esto fallará con basura masiva en su historial de git, empujado a compartir con otros, y luego difícil o imposible de eliminar después de eso.

Cuestiones relacionadas