Как оформить заказ в Git по дате?

314

Я работаю над регрессом в исходном коде. Я хотел бы сказать Git: «извлечение источника на основе параметризованной даты / времени». Это возможно?

У меня также есть изменения в моем текущем представлении, которые я не хочу терять. В идеале я хотел бы переключаться между текущим источником и какой-либо интересующей меня версией, основываясь на предыдущей дате.

Амир Афганский
источник
9
На случай, если вы не знаете об этом, git bisect отлично подходит для поиска регрессий. Я бы сказал, используйте синтаксис {1 год назад}, как сказал Энди, чтобы найти заведомо хороший коммит, а затем используйте его в качестве начальной git bisect goodточки.
MatrixFrog
Я чувствую, что это хороший вариант использования tags.
Джесс

Ответы:

365

Чтобы сохранить ваши текущие изменения

Вы можете хранить свою работу подальше, не передавая ее, с git stash. Вы бы, чем использовать, git stash popчтобы вернуть его. Или вы можете (как сказал Карлито ) git commitэто в отдельную ветку.

Оформить заказ по дате, используя rev-parse

Вы можете оформить коммит к определенной дате, используя rev-parseвот так:

git checkout 'master@{1979-02-26 18:30:00}'

Более подробную информацию о доступных опциях можно найти в git-rev-parse.

Как отмечено в комментариях, этот метод использует reflog, чтобы найти коммит в вашей истории. По умолчанию срок действия этих записей истекает через 90 дней . Хотя синтаксис использования reflog менее подробный, вы можете вернуться только на 90 дней назад.

Оформить заказ по дате, используя rev-list

Другой вариант, который не использует reflog, это использовать rev-listдля получения фиксации в определенный момент времени с помощью:

git checkout `git rev-list -n 1 --first-parent --before="2009-07-27 13:37" master`

Обратите внимание на --first-parent, если вам нужна только ваша история, а не версии, внесенные слиянием. Это то, что вы обычно хотите.

Энди
источник
2
@Rocky Можете ли вы дать нам больше деталей, Рокки? Что вы вводите в командной строке и почему вы говорите, что это не работает? Вы получаете сообщение об ошибке?
Энди
8
@Rocky: проблема в том, что параметр должен быть заключен в кавычки, иначе bash разделяет аргументы в пробелах. Попробуй git co 'master@{2 days ago}'.
Марк Уилден
13
Примечание: в зависимости от того, как далеко вы вернетесь, это может не сработать, поскольку используется журнал reflog (срок действия которого истекает через некоторое время). Вы увидите «предупреждение: журнал для« мастера »возвращается только к ...». Решение Рокки будет работать всегда. Git Checkoutgit rev-list -n 1 --before="2009-07-27 13:37" master
Марк Надиг
3
Я отредактировал ваш ответ, потому что обратные ссылки устарели и их трудно читать. Подоболочки $(...)являются предпочтительными.
Амеди Ван Гасс
1
@ Энди С Днем Рождения, Энди! (при условии, что это означало 1979-02-26 :))
Дэвид Блевинс
123

Решение Энди не работает для меня. Здесь я нашел другой способ:

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`

Git: оформить заказ по дате

скалистый
источник
3
Когда я выполняю вышеуказанную команду, у меня появляются error: unknown switch `n'идеи, как обойти это?
Тим
15

Похоже, вам нужно что-то вроде этого: Git checkout на основе даты

Другими словами, вы используете, rev-listчтобы найти коммит, а затем используете checkout, чтобы фактически получить его.

Если вы не хотите потерять свои поэтапные изменения, проще всего будет создать новую ветку и зафиксировать их в этой ветке. Вы всегда можете переключаться между ветвями.

Изменить: ссылка не работает, поэтому вот команда:

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`
деревенщина
источник
2
Отличная ссылка! Так git checkout branch@{date}перестает работать, когда истекает reflog, но вы можете использовать git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`.
cdunn2001
10

Тем, кто предпочитает трубу командной подстановке

git rev-list -n1 --before=2013-7-4 master | xargs git checkout
Стивен Пенни
источник
9

В моем случае -n 1опция не работает. В Windows я обнаружил, что следующая последовательность команд работает нормально:

git rev-list -1 --before="2012-01-15 12:00" master

Это возвращает SHA соответствующего коммита на указанную дату, а затем:

git checkout SHA
BartoszKP
источник
4

git rev-parseРешение , предложенное @Andy работает нормально , если дата вас интересует это совершить дату . Однако, если вы хотите оформить заказ на основе даты автора , rev-parseне будет работать, потому что он не предлагает возможность использовать эту дату для выбора фиксаций. Вместо этого вы можете использовать следующее.

git checkout $(
  git log --reverse --author-date-order --pretty=format:'%ai %H' master |
  awk '{hash = $4} $1 >= "2016-04-12" {print hash; exit 0 }
)

(Если вы также хотите указать время, используемое $1 >= "2016-04-12" && $2 >= "11:37"в предикате awk .)

Диомидис Спинеллис
источник
3

rev-listЕсли вы хотите найти самую последнюю фиксацию слияния из вашей основной ветви в вашу производственную ветвь (в качестве чисто гипотетического примера), перейдем далее к опции:

git checkout `git rev-list -n 1 --merges --first-parent --before="2012-01-01" production`

Мне нужно было найти код, который был на производственных серверах на определенную дату. Это нашло это для меня.

egerlach
источник
2

Если вы хотите иметь возможность вернуться к точной версии репозитория во время сборки, лучше всего пометить коммит, из которого вы делаете сборку.

Другие ответы предоставляют методы для возврата хранилища в самый последний коммит в ветке на определенное время, но их не всегда достаточно. Например, если вы строите из ветки, а затем удаляете ветку, или строите из ветки, которая позже была перебазирована, созданный вами коммит может стать «недоступным» в git из любой текущей ветки. Недоступные объекты в git могут в конечном итоге быть удалены при сжатии хранилища.

Помещение тега в коммит означает, что он никогда не станет недоступным, независимо от того, что вы делаете с ветками впоследствии (за исключением удаления тега).

antlersoft
источник
Хотя это не дает мне ответа, который я ищу, оно заслуживает хорошего упоминания за то, что оно указывает на аспект, не упомянутый до сих пор. Это может быть источником проблем, которые мешают вам выбрать правильную версию.
Мануэльвигарсия
1
git rev-list -n 1 --before="2009-07-27 13:37" origin/master

возьмите напечатанную строку (например, XXXX) и выполните:

git checkout XXXX
Лука С.
источник
2
Разве это не дубликат ответа @bartoszkp? просто добавив ссылку на происхождение, должен быть комментарий к другому ответу ...
manuelvigarcia
да, на самом деле почти, просто объясняя, что копировать, для тех, кто не знает, что такое SHA (как и я), в моем случае этот текст был неясным, и это мой код после того, как было найдено решение, а не скопировано, фактически вы можете увидеть варианты тоже немного отличаются
Luca C.