git commit с датой до 1973 года не удалось [дублировать]

myList = [[1]*4] * 3 создает один объект списка [1,1,1,1] в памяти и копирует его ссылку 3 раза. Это эквивалентно obj = [1,1,1,1]; myList = [obj]*3. Любая модификация obj будет отражена в трех местах, где obj упоминается в списке. Правильным утверждением будет:

myList = [[1]*4 for _ in range(3)]

или

myList = [[1 for __ in range(4)] for _ in range(3)]

. Важно отметить, что * оператор в основном используется для создания список литералов. Поскольку 1 является литералом, значит, obj =[1]*4 создаст [1,1,1,1], где каждый 1 будет атомарным, а не ссылкой 1, повторяемым 4 раза. Это означает, что если мы obj[2]=42, то obj станет [1,1,42,1] не [42,42,42,42], как могут предположить некоторые.

29
задан John O 28 July 2014 в 00:12
поделиться

4 ответа

Еще совершает c64b9b8 (git 0.99, май 2005), время всегда упоминалось как

<date>

Дата в секундах с epoch '

commit 6eb8ae0 определяет дату как unsigned long с апреля 2005 года.

TLDR;

]

date до unix epoch может быть сохранен, но не может быть уверен, что он будет правильно представлен.


Попытка представить дату перед попыткой до: см. эта нить

Дата, которую я пытаюсь установить, - 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», а скорее проверка каждого изменения, чтобы убедиться, что вы не вводите новые ошибки, и что код правильно обрабатывает подписанные типы. Вот почему никто этого не сделал. ;)

23
ответ дан VonC 17 August 2018 в 21:32
поделиться

Вы можете сохранить их, но ничто не покажет их, как вы ожидали (пока).

Внутренний формат Git сохраняет данные фиксации в виде числовой строки. например ::

$ git cat-file -p aa2706463fdeb51d6f9d0e267113b251888cf7f5
...
author Junio C Hamano <gitster@pobox.com> 1383318892 -0700
committer Junio C Hamano <gitster@pobox.com> 1383318892 -0700

Я не считаю, что требуется, чтобы это число было положительным. Однако большинство реализаций, включая git, анализируют его как неподписанное число и не будут корректно отображать эти даты. Например, в builtin/blame.c :

    *time = strtoul(ident.date_begin, NULL, 10);

So; использование отрицательных времен - это не то, что вы можете легко сделать с текущими инструментами или отображать с помощью текущих инструментов, но модель Git означает, что коммиты, включая их, будут сохраняться без изменений в репозитории.

2
ответ дан Joe 17 August 2018 в 21:32
поделиться

Я просто спрятался с git hash-object и создал следующий объект commit:

tree 5efb9bc29c482e023e40e0a2b3b7e49cec842034
author x <x@x.com> -134607600 -0500
committer z <z@z.com> 1402404632 -0600

blah blah

Вы заметите, что дата автора установлена ​​на отрицательное число. Затем я использовал git update-ref, чтобы попытаться связать объект commit ... не повезло, я получаю следующий вывод, когда я делаю журнал git:

$ git log
commit 2303e7012001a3cc1c3dec806d0902008e1257a8
Author: x <x@x.com>
Date:   (null)

    blah blah

Sourcetree также смущен:

Parents: 
Author: x <x@x.com>
Date: Monday, January 01, 0001 12:00:00 AM
Committer: z <z@z.com>
Commit Date: Tuesday, June 10, 2014 7:50:32 AM

(я думаю, что я забыл включить родительский объект фиксации ...)

Точно так же даты в далеком будущем тоже не работают (указывая, что он, вероятно, не обрабатывает это как 64-битное значение, даже если оно одно).

Я не уверен, что этот ответ квалифицируется как «нет, вы не можете этого сделать» или «вы можете, но он не работает» Что ж". Один из них нуждается в модифицированном клиенте, чтобы иметь возможность просматривать журналы git с правильными датами, удаляя все возможные выгоды для этого. Если кто-то знает отличную команду git log, которая будет правильно анализировать эти временные метки (они ушли в этот момент?!?!), Пожалуйста, исправьте меня.

0
ответ дан John O 17 August 2018 в 21:32
поделиться

Git внутренне поддерживает даты как временную метку Unix и смещение от UTC, поэтому невозможно установить дату фиксации до эпохи Unix.

Вы должны запускать другую версию Git, чем У меня на моей системе CentOS 6.5 (которая предоставляет Git 1.7.1), по крайней мере, у вас появляется сообщение об ошибке ... Если я попытаюсь установить невозможную дату фиксации с помощью Git 1.7.1, то коммит будет успешным и беззвучно будет использовать текущий время для даты фиксации; если я попытаюсь выполнить ту же операцию с использованием «возможной» даты фиксации, она будет успешной и запишет предполагаемую дату фиксации.

2
ответ дан patbarron 17 August 2018 в 21:32
поделиться
  • 1
    Временная метка unix представляет собой 32-битное целое число. Отрицательные числа соответствуют, как можно было бы подумать, и поскольку вы получаете 2.something миллиард из них и 2 миллиарда секунд составляет около 64 лет, вы сможете вернуться к 1906 году плюс изменения. Или я понимаю. Использует ли что-нибудь даже без знака int для временных меток? – John O 14 February 2014 в 23:10
  • 2
    Если смотреть в исходном коде, то дата фиксации записывается в структуре фиксации как unsigned long: github.com/git/git/blob/master/commit.h – patbarron 14 February 2014 в 23:13
  • 3
    И я признаю, что я никогда не думал о том, что время_t подписано, что означает, что даты до эпохи могут быть представлены, поэтому технически это будет ошибкой в ​​Git (или, по крайней мере, ошибкой документации ... .) – patbarron 14 February 2014 в 23:20
Другие вопросы по тегам:

Похожие вопросы: