ACTUALIZACIÓN : Mi solución ahora está empaquetada en Debian / Ubuntu / Mint, Fedora, Gentoo y posiblemente otras distribuciones:
https://github.com/MestreLion/git-tools#install
sudo apt install git-restore-mtime # Debian/Ubuntu/Mint
yum install git-tools # Fedora/ RHEL / CentOS
emerge dev-vcs/git-tools # Gentoo
En mi humilde opinión, no almacenar marcas de tiempo (y otros metadatos como permisos y propiedad) es una gran limitación de git.
El razonamiento de Linus de que las marcas de tiempo sean dañinas solo porque "confunden make" es poco convincente :
make clean es suficiente para solucionar cualquier problema.
Se aplica solo a proyectos que utilizan make, principalmente C / C ++. Es completamente discutible para scripts como Python, Perl o documentación en general.
Solo hay daño si aplica las marcas de tiempo. No haría ningún daño almacenarlos en repositorio. Aplicarlos podría ser una --with-timestampsopción sencilla para git checkouty amigos ( clone, pulletc.), a discreción del usuario .
Tanto Bazaar como Mercurial almacenan metadatos. Los usuarios pueden aplicarlos o no al momento de pagar. Pero en git, dado que las marcas de tiempo originales ni siquiera están disponibles en el repositorio, no existe tal opción.
Entonces, para una ganancia muy pequeña (no tener que volver a compilar todo) que es específica de un subconjunto de proyectos, gitya que un DVCS general se paralizó , se pierde parte de la información de los archivos y, como dijo Linus, es INFEASIBLE hacerlo Es ahora. Sad .
Dicho esto, ¿puedo ofrecer 2 enfoques?
1 - http://repo.or.cz/w/metastore.git , por David Härdeman. Intenta hacer lo que git debería haber hecho en primer lugar : almacena metadatos (no solo marcas de tiempo) en el repositorio cuando se confirma (a través de un gancho de confirmación previa) y los vuelve a aplicar al extraer (también a través de ganchos).
2 - Mi versión humilde de un script que usé antes para generar tarballs de lanzamiento. Como se mencionó en otras respuestas, el enfoque es un poco diferente : aplicar para cada archivo la marca de tiempo de la confirmación más reciente donde se modificó el archivo.
- git-restore-mtime , con muchas opciones, admite cualquier diseño de repositorio y se ejecuta en Python 3.
A continuación se muestra una versión realmente básica del script, como prueba de concepto, en Python 2.7. Para el uso real, recomiendo encarecidamente la versión completa anterior:
#!/usr/bin/env python
# Bare-bones version. Current dir must be top-level of work tree.
# Usage: git-restore-mtime-bare [pathspecs...]
# By default update all files
# Example: to only update only the README and files in ./doc:
# git-restore-mtime-bare README doc
import subprocess, shlex
import sys, os.path
filelist = set()
for path in (sys.argv[1:] or [os.path.curdir]):
if os.path.isfile(path) or os.path.islink(path):
filelist.add(os.path.relpath(path))
elif os.path.isdir(path):
for root, subdirs, files in os.walk(path):
if '.git' in subdirs:
subdirs.remove('.git')
for file in files:
filelist.add(os.path.relpath(os.path.join(root, file)))
mtime = 0
gitobj = subprocess.Popen(shlex.split('git whatchanged --pretty=%at'),
stdout=subprocess.PIPE)
for line in gitobj.stdout:
line = line.strip()
if not line: continue
if line.startswith(':'):
file = line.split('\t')[-1]
if file in filelist:
filelist.remove(file)
#print mtime, file
os.utime(file, (mtime, mtime))
else:
mtime = long(line)
# All files done?
if not filelist:
break
El rendimiento es bastante impresionante, incluso para proyectos monstruosos wine, gito incluso para el kernel de Linux:
bash
# 0.27 seconds
# 5,750 log lines processed
# 62 commits evaluated
# 1,155 updated files
git
# 3.71 seconds
# 96,702 log lines processed
# 24,217 commits evaluated
# 2,495 updated files
wine
# 13.53 seconds
# 443,979 log lines processed
# 91,703 commits evaluated
# 6,005 updated files
linux kernel
# 59.11 seconds
# 1,484,567 log lines processed
# 313,164 commits evaluated
# 40,902 updated files