Как оформить заказ в 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

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`

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


2

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

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

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


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

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

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

git checkout XXXX

2
Разве это не дубликат ответа @bartoszkp? просто добавив ссылку на происхождение, должен быть комментарий к другому ответу ...
manuelvigarcia

да, на самом деле почти, просто объясняя, что копировать, для тех, кто не знает, что такое SHA (как и я), в моем случае этот текст был неясным, и это мой код после того, как было найдено решение, а не скопировано, фактически вы можете увидеть варианты тоже немного отличаются
Luca C.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.