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

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

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

14 ответов

Решение

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

Вы можете хранить свою работу подальше, не совершая ее, с 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 --before="2009-07-27 13:37" master`

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

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

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

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

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

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

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

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

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

git rev-list -n1 --before=2013-7-4 master | xargs git checkout

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

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

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

git checkout SHA

Напоминание, начиная с Git 2.23 (август 2019 г.)

  • переключиться на новую ветку из прошлой фиксации по дате:

            git switch -c newBranch $(git rev-list -n1 --before=yyyy-mm-dd main)
    
  • восстановить файл на прошлую дату в текущем рабочем дереве

            git restore -SW -s $(git rev-list -n1 --before=yyyy-mm-dd main) -- path/to/file
    

Не используйте старые, устаревшие и запутанные git checkoutкоманда в 2021/2022: а также точно описать, что они делают (работают только с ветвями для git switch, и только с файлами для git restore)

Не используйте ``: предпочитайте более современный $(command substitution)синтаксис вместо устаревшего синтаксиса обратной кавычки.

Чтобы создать новую ветку из кассы, используйте опцию -b с новым именем ветки.

      git checkout -b 19July2021 `git rev-list -n1 --before=2021-7-19 master`

Вы можете избежать git switch, когда вы находитесь в состоянии "отсоединен HEAD"

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.)

Вам нужно только небольшое изменение, если вы достигнете предела рефлога (дата, когда вы клонировали репо или 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, похоже, он работает, даже если у вас нет рефлогинга на дату, которую вы хотите проверить!!!

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

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

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

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

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

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

Вот версия псевдонима, которую я использую для оформления заказа по относительному времени:

      [alias]
    parsedate = "!set -x ;arg1=\"$1\" && shift && which gdate &> /dev/null && gdate -d \"$arg1\" || date -d \"$arg1\""
    codate = "!d=\"$(git parsedate \"$1\")\" && shift && git checkout \"$(git rev-list -n1 --first-parent --before=\"$d\" HEAD)\""

Это позволяет вам проверить свои изменения, сделанные 2 месяца назад, в новую ветку с именем testиспользуя следующую команду:

      git codate '2 months ago' -b test

Это не будет работать на мелком клоне, поэтому сначала удалите его с помощью:

      git fetch --unshallow

Если вы получаете неполную ошибку, вы можете найти помощь в отличном ответе на git fatal: error in object: unshallow

Требует GNU coreutils и работает на Linux и macOS с использованием brew.

Установить на macos с помощью brew install coreutils.

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

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

git checkout XXXX

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

      git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master FILEPATH` FILEPATH
Другие вопросы по тегам