AKTUALIZACJA : Moje rozwiązanie jest teraz spakowane w dystrybucji Debian / Ubuntu / Mint, Fedora, Gentoo i prawdopodobnie innych:
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
IMHO, nieprzechowywanie sygnatur czasowych (i innych metadanych, takich jak uprawnienia i własność), jest dużym ograniczeniem git.
Rozumowanie Linusa, że sygnatury czasowe są szkodliwe tylko dlatego, że „dezorientuje make”, jest kiepskie :
make clean wystarczy, aby naprawić wszelkie problemy.
Dotyczy tylko projektów, które używają make, głównie C / C ++. Jest to całkowicie dyskusyjne w przypadku skryptów takich jak Python, Perl lub ogólnie dokumentacji.
Szkoda jest tylko wtedy, gdy zastosujesz znaczniki czasu. Przechowywanie ich w repozytorium nie byłoby szkodliwe . Ich stosowania może być prostym --with-timestampsrozwiązaniem dla git checkouti przyjaciele ( clone, pulletc), na użytkownika uznania.
Zarówno Bazaar, jak i Mercurial przechowują metadane. Użytkownicy mogą je zastosować lub nie podczas płatności. Ale w git, ponieważ oryginalne znaczniki czasu nie są nawet dostępne w repozytorium, nie ma takiej opcji.
Tak więc, dla bardzo małego zysku (brak konieczności ponownej kompilacji wszystkiego), który jest charakterystyczny dla podzbioru projektów, gitponieważ ogólny DVCS został uszkodzony , niektóre informacje z plików są tracone i, jak powiedział Linus, jest to NIEDOPROGRAMOWANE. teraz. Smutne .
To powiedziawszy, czy mogę zaoferować 2 podejścia?
1 - http://repo.or.cz/w/metastore.git , autor: David Härdeman. Próbuje zrobić to, co git powinno było zrobić w pierwszej kolejności : przechowuje metadane (nie tylko znaczniki czasu) w repozytorium podczas zatwierdzania (za pomocą haka przed zatwierdzeniem) i ponownie je stosuje podczas ściągania (również za pomocą haków).
2 - Moja skromna wersja skryptu, którego użyłem wcześniej do generowania paczek z wydaniami. Jak wspomniano w innych odpowiedzi, podejście jest trochę inaczej : do zastosowania dla każdego akt datownik z najnowszym popełnienia gdzie plik został zmodyfikowany.
- git-restore-mtime , z wieloma opcjami, obsługuje dowolny układ repozytorium i działa w Pythonie 3.
Poniżej znajduje się naprawdę prosta wersja skryptu, jako dowód słuszności koncepcji, w Pythonie 2.7. Do rzeczywistego użytku zdecydowanie polecam pełną wersję powyżej:
#!/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
Wydajność jest imponująca, nawet w przypadku potwornych projektów wine, gita nawet jądra Linuksa:
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