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

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

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


person Amir Afghani    schedule 09.08.2011    source источник
comment
На всякий случай, если вы не знаете об этом, git bisect отлично подходит для поиска регрессий. Я бы сказал, используйте синтаксис {1 год назад}, как сказал Энди, чтобы найти заведомо хороший коммит, а затем используйте его в качестве начальной точки git bisect good.   -  person MatrixFrog    schedule 09.08.2011
comment
Мне кажется, это хороший вариант использования tags.   -  person Jess    schedule 02.11.2017


Ответы (10)


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

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

Оформить заказ по дате с помощью rev-parse

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

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

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

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

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

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

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

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

person Andy    schedule 09.08.2011
comment
@Rocky Можете ли вы дать нам более подробную информацию, Рокки? Что вы вводите в командной строке и почему вы говорите, что это не работает? Вы получаете сообщение об ошибке? - person Andy; 15.12.2011
comment
вот сообщение: git co master@{2011-11-11} предупреждение: журнал для «мастера» возвращается только во вторник, 13 декабря 2011 г., 02:19:31 +0000. - person Rocky; 16.12.2011
comment
другое: git co master@{2 days ago} ошибка: pathspec 'master@{2' не соответствует ни одному файлу(ам), известному git. ошибка: pathspec 'days' не соответствует ни одному файлу(ам), известному git. ошибка: pathspec 'назад}' не соответствует ни одному файлу(ам), известному git. - person Rocky; 16.12.2011
comment
@Rocky: проблема в том, что параметр нужно заключать в кавычки, иначе bash разделяет аргументы пробелами. Попробуйте git co 'master@{2 days ago}'. - person Mark Wilden; 11.02.2012
comment
Примечание: в зависимости от того, как далеко вы продвинулись, это может не сработать, потому что используется reflog (срок действия которого истекает через некоторое время). Вы увидите «предупреждение: журнал для «мастера» восходит только к ...». Решение Рокки будет работать всегда. Git-касса git rev-list -n 1 --before="2009-07-27 13:37" master - person Mark Nadig; 22.03.2012
comment
да. См. ссылку, опубликованную Carleeto и Rocky. - person cdunn2001; 04.04.2012
comment
Я отредактировал ваш ответ, потому что обратные кавычки устарели и их трудно читать. Подоболочки $(...) предпочтительнее. - person Amedee Van Gasse; 15.01.2016
comment
Обратите внимание, что решение с rev-list не будет работать должным образом, когда задействованы слияния. В частности, он может выбрать один из коммитов на любой из объединяемых веток, даже если рассматриваемый коммит не был на самом деле на master в то время. - person Michał Górny; 26.05.2016
comment
Обратите внимание, что здесь используется дата коммита, что обычно нормально. См. Ниже ответ, в котором используется дата автора. - person Diomidis Spinellis; 13.08.2016
comment
Просто к сведению. master — это локальная ветка. Если он не обновлен, вы можете не получить ожидаемые файлы. Вместо этого вы можете использовать «происхождение/мастер» - person user959690; 09.11.2017
comment
@Энди С 40-летием, Энди! (если предположить, что это означало 1979-02-26 :)) - person David Blevins; 26.02.2019
comment
Похоже, что ветвь и дата являются необязательными, поэтому это также работает, если вас интересует только дата: git checkout '@{1979-02-26}' - person Nick McCurdy; 26.04.2020
comment
Я просто потратил много времени, потому что это решение дает мне вершину главной ветки! - person Frank Puck; 04.02.2021

Решение Энди не работает для меня. Вот нашел еще способ:

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

Git: проверка по дате

person Rocky    schedule 15.12.2011
comment
Когда я выполняю приведенную выше команду, я получаю error: unknown switch `n' какие-либо идеи, как обойти это? - person Tim; 19.04.2019
comment
@Tim Запустите его в две части: сначала запустите git rev-list и только после этого запустите git checkout с коммитом, который вы получили из первой команды. - person David Mulder; 28.06.2020
comment
Вместо -n 1 вы должны использовать --max-count=1 - person John Henckel; 04.09.2020
comment
Вы должны объяснить, для чего нужны опции. Почему -n 1? Какая разница, не пройти ли его? - person Frank Puck; 09.02.2021

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

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

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

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

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`
person Carl    schedule 09.08.2011
comment
Отличная ссылка! Таким образом, git checkout branch@{date} перестает работать, когда истечет срок действия журнала ссылок, но вы можете использовать git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`. - person cdunn2001; 04.04.2012

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

git rev-list -n1 --before=2013-7-4 master | xargs git checkout
person Steven Penny    schedule 09.12.2013

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

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

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

git checkout SHA
person BartoszKP    schedule 08.12.2015

Решение 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.)

person Diomidis Spinellis    schedule 13.08.2016

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

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

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

person egerlach    schedule 07.10.2013

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

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

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

person antlersoft    schedule 04.12.2015
comment
Хотя это не дает мне ответа, который я ищу, он заслуживает хорошего упоминания за указание на аспект, не упомянутый до сих пор. Это может быть источником проблем, которые мешают вам найти нужную версию. - person manuelvigarcia; 28.01.2019

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

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

git checkout XXXX
person Luca C.    schedule 05.05.2017
comment
Разве это не дубликат ответа @bartoszkp? просто добавив ссылку на происхождение, должен быть комментарий к другому ответу... - person manuelvigarcia; 28.01.2019
comment
да на самом деле почти, просто уточнил что копировать для тех кто не знает что такое SHA (как я), в моем случае тот текст был не понятен а это мой код после нахождения решения, не скопированный, собственно сами видите варианты тоже немного отличаются - person Luca C.; 29.01.2019

Вам нужно только небольшое изменение, если вы достигли предела reflog (дата, когда вы клонировали репо, или 90 дней истории, как видно из других заметок)

git checkout `git rev-list -1 --before="Jan 17 2020" HEAD`

И вы также можете использовать

git checkout `git rev-list -1 --before="Jan 17 2020 8:06 UTC-8" HEAD`

он проверит предыдущую фиксацию, связанную с введенной датой или датой-временем, и увидит, что вы можете использовать модификаторы для даты, я думаю, если вы не используете UTC+-N, он просто использует время UTC.

Обратите внимание, что я только изменил master на HEAD, похоже, это работает, даже если у вас нет reflog на дату, которую вы хотите проверить !!!

person tyoc213    schedule 28.08.2020