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