Можно ли установить фиксацию git для отметки времени до 1970 года?
Временные метки Unix подписываются 32-битными целыми числами (64 бит на некоторых системах сегодня, или так я понимаю). На некоторых программных продуктах это позволяет использовать даты, начиная с 1903 года или около того.
Однако, когда я пытаюсь сделать следующее:
git commit -m "this is a test commit" --date="1960-04-07 18:00:00"
Я получаю ошибку "фатальный: недопустимый формат даты".
Это не очень практично (я не путешественник во времени), но мне было интересно использовать git для исторических целей. Может ли это быть принудительно с помощью команды git plumbing? В отношении связанной заметки: git всегда использует 32-битную метку времени, или это зависит от среды, на которой она построена?
Ответы
Ответ 1
Еще commit c64b9b8 (git 0.99, май 2005), время всегда упоминалось как
<date>
Дата в секундах с эпоха '
commit 6eb8ae0 определяет дату как unsigned long
с апреля 2005 года.
TL;DR;
дата до эпохи unix может быть сохранена, но не может быть уверенной, что она правильно представлена.
Попытка представить дату раньше была предпринята раньше: см. этот поток
Дата, которую я пытаюсь установить, - это 4 октября 1958 года, которая находится вокруг timestamp -354808800.
Первый метод, используя флаги commit --date
с ISO 8601: он говорит "invalid date
".
Вторая техника, описанная в архиве git ml, не используя фарфор:
git commit
git cat-file -p HEAD > tmp.txt
# at this point, edit the file to replace the timestamp
git hash-object -t commit -w tmp.txt
#=> 2ee8fcc02658e23219143f5bcfe6f9a4615745f9
git update-ref -m 'commit: foo' refs/heads/master \
2ee8fcc02658e23219143f5bcfe6f9a4615745f9
Дата фиксации эффективно обновляется, но git show
фиксирует дату до нуля (Jan 1 1970
). tig(1)
отображает 55 years ago
, чтобы фактическая дата фиксации была правильно сохранена.
Последняя проблема: при попытке нажать эту фиксацию на удаленный репозиторий:
#=> remote: error: object 2ee8fcc02658e23219143f5bcfe6f9a4615745f9:invalid
# author/committer line - bad date
#=> remote: fatal: Error in object
#=> error: unpack failed: index-pack abnormal exit
Наконец, при запуске test-date
из git источников:
./test-date show -354808800
#=> -354808800 -> in the future
Обсуждение в то время:
Я не уверен, что на самом низком уровне нет никакой неспортивности.
Мы свободно обмениваемся между time_t и unsigned long в низкоуровневом коде даты. Вероятно, это работает, потому что, как правило, выполняется работа с битами между подписанными и неподписанными типами, если вы в конечном итоге получаете тот тип, который вы хотите.
Но это не обязательно переносимо, и могут быть тонкие ошибки. Посмотрите, например, мои последние 9ba0f033.
Хорошая новость, что это просто проблема с кодом. Формат данных прекрасен. Просто нужно, чтобы кто-то прошел код и переключил все "unsigned long
" на "long long
" (или time_t
, или даже "gittime_t
", если мы хотим отвлечь его).
и исправление алгоритма анализатора, по крайней мере, в tm_to_time_t()
Это не просто "sed s/unsigned long/long long
", а проверка всех изменений, чтобы убедиться, что вы не вводите новые ошибки, и что код правильно обрабатывает подписанные типы.
Вот почему никто этого не сделал.;)
Ответ 2
Git внутренне поддерживает даты как временную метку Unix и смещение от UTC, поэтому невозможно установить дату фиксации до эпохи Unix.
У вас должна быть другая версия Git, чем у меня в моей системе CentOS 6.5 (которая предоставляет Git 1.7.1), по крайней мере у вас появляется сообщение об ошибке... Если я попытаюсь установить невозможная дата фиксации с использованием Git 1.7.1, фиксация завершается успешно и молча использует текущее время для даты фиксации; если я попытаюсь выполнить ту же операцию с использованием "возможной" даты фиксации, она будет успешной и запишет предполагаемую дату фиксации.
Ответ 3
Вы можете сохранить их, но ничто не покажет их, как вы ожидали (пока).
Внутренний формат Git сохраняет данные фиксации как числовую строку. например:.
$ git cat-file -p aa2706463fdeb51d6f9d0e267113b251888cf7f5
...
author Junio C Hamano <[email protected]> 1383318892 -0700
committer Junio C Hamano <[email protected]> 1383318892 -0700
Я не считаю, что это требование было положительным. Однако большинство реализаций, включая git
, анализируют его как неподписанное число и не будут корректно отображать эти даты. Например, в builtin/blame.c
:
*time = strtoul(ident.date_begin, NULL, 10);
Итак, использование отрицательных времен - это не то, что вы можете легко сделать с текущими инструментами или отображать с помощью текущих инструментов, но модель Git означает, что коммиты, включая их, останутся неизменными в репозитории.
Ответ 4
Я просто сменил хэш-объект git и создал следующий объект фиксации:
tree 5efb9bc29c482e023e40e0a2b3b7e49cec842034
author x <[email protected]> -134607600 -0500
committer z <[email protected]> 1402404632 -0600
blah blah
Вы заметите, что дата автора установлена на отрицательное число. Затем я использовал git update-ref, чтобы попытаться связать объект commit в... не повезло, я получаю следующий вывод, когда я делаю журнал git:
$ git log
commit 2303e7012001a3cc1c3dec806d0902008e1257a8
Author: x <[email protected]>
Date: (null)
blah blah
Sourcetree также смущен:
Parents:
Author: x <[email protected]>
Date: Monday, January 01, 0001 12:00:00 AM
Committer: z <[email protected]>
Commit Date: Tuesday, June 10, 2014 7:50:32 AM
(Я думаю, что забыл включить родительский объект фиксации...)
Точно так же даты в далеком будущем тоже не работают (указывая, что, вероятно, это не рассматривается как 64-битное значение, даже если оно одно).
Я не уверен, соответствует ли этот ответ "нет, вы не можете этого сделать" или "вы можете, но это не работает". Один из них нуждается в модифицированном клиенте, чтобы иметь возможность просматривать журналы git с правильными датами, удаляя все возможные преимущества для этого. Если кто-то знает отличную команду git log, которая будет правильно анализировать эти временные метки (они ушли в этот момент?!?!), Пожалуйста, поправьте меня.