ОНОВЛЕННЯ : Моє рішення тепер упаковано в Debian / Ubuntu / Mint, Fedora, Gentoo та, можливо, інші дистрибутиви:
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, не зберігання міток часу (та інших метаданих, таких як дозволи та право власності) є великим обмеженням git.
Обгрунтування Лінуса, що мітки часу є шкідливими лише тому, що це "заплутує make", кульгає .
make clean достатньо, щоб усунути будь-які проблеми.
Застосовується лише до проектів, які використовують make, переважно C / C ++. Це абсолютно спірне питання для таких сценаріїв, як Python, Perl або документація загалом.
Шкода є лише в тому випадку, якщо ви застосовуєте позначки часу. Не було б шкоди зберігати їх у репо. Застосовуючи їх може бути простим --with-timestampsваріантом git checkoutі друзів ( clone, і pullт.д.), у користувача розсуд.
І Bazaar, і Mercurial зберігають метадані. Користувачі можуть застосовувати їх чи ні під час реєстрації. Але в git, оскільки оригінальні мітки часу навіть відсутні в репо, такого варіанту немає.
Отже, для дуже маленького виграшу (без необхідності перекомпілювати все), який є специфічним для підмножини проектів, gitоскільки загальний DVCS був скалічений , втрачається деяка інформація про файли , і, як сказав Лінус, це неможливо зробити це зараз. Сумно .
Тим не менш, я можу запропонувати 2 підходи?
1 - http://repo.or.cz/w/metastore.git , Девід Хердеман. Намагається зробити те, що git слід було зробити в першу чергу : зберігає метадані (а не лише мітки часу) у репо під час комітування (за допомогою гачка перед фіксацією) і повторно застосовує їх під час витягування (також за допомогою хуків).
2 - Моя скромна версія сценарію, який я використовував раніше для створення тарбалів випуску. Як уже згадувалося в інших відповідях, підхід трохи відрізняється : застосовувати для кожного файлу , тимчасова мітка з самої останньої фіксації , де був змінений файл.
- git-restore-mtime , з великою кількістю опцій, підтримує будь-який макет сховища та працює на Python 3.
Нижче представлена справді гола версія сценарію, як доказ концепції, на Python 2.7. Для фактичного використання я настійно рекомендую повну версію вище:
#!/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
Продуктивність дуже вражає, навіть для монстра проектів wine, gitабо навіть ядра 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