Как можно изменить временную метку старого коммита в Git?
Ответы на вопрос Как изменить существующие, неопубликованные коммиты? опишите способ изменения предыдущих сообщений коммита, которые еще не были переданы в апстрим. Новые сообщения наследуют временные метки оригинальных коммитов. Это кажется логичным, но есть ли способ также переустановить время?
32 ответа
Использование git filter-branch
с фильтром env, который sets GIT_AUTHOR_DATE
а также GIT_COMMITTER_DATE
для конкретного хэша коммита, который вы хотите исправить.
Это аннулирует это и все будущие хэши.
Пример:
Если вы хотите изменить даты совершения 119f9ecf58069b265ab22f1f97d2b648faf932e0
Вы могли бы сделать это с чем-то вроде этого:
git filter-branch --env-filter \
'if [ $GIT_COMMIT = 119f9ecf58069b265ab22f1f97d2b648faf932e0 ]
then
export GIT_AUTHOR_DATE="Fri Jan 2 21:38:53 2009 -0800"
export GIT_COMMITTER_DATE="Sat May 19 01:01:01 2007 -0700"
fi'
Вы можете сделать интерактивную перебазировку и выбрать редактировать для коммита, дату которого вы хотели бы изменить. Когда процесс rebase останавливается для внесения изменений в коммит, который вы вводите, например:
git commit --amend --date="Wed Feb 16 14:00 2011 +0100"
После этого вы продолжаете интерактивную перебазирование.
ОБНОВЛЕНИЕ (в ответ на комментарий Studgeek): чтобы изменить дату фиксации вместо даты автора:
GIT_COMMITTER_DATE="Wed Feb 16 14:00 2011 +0100" git commit --amend
Строки выше устанавливают переменную окружения GIT_COMMITTER_DATE, которая используется в коммите на изменение.
Все проверено в Git Bash.
Лучший способ обработать все эти предложения в одной команде:
LC_ALL=C GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
Это установит дату последнего коммита и дату автора на "прямо сейчас".
Просто делать git commit --amend --reset-author --no-edit
, Для старых коммитов вы можете сделать интерактивную перебазировку и выбрать edit
для коммита, дату которого вы хотите изменить.
git rebase -i <ref>
Затем измените коммит --reset-author
а также --no-edit
чтобы изменить дату автора на текущую дату:
git commit --amend --reset-author --no-edit
Наконец, продолжите интерактивную ребазу:
git rebase --continue
Я написал скрипт и пакет Homebrew для этого. Супер прост в установке, вы можете найти его на GitHub PotatoLabs/git-redate
стр.
Синтаксис:
git redate -c 3
Вам просто нужно бежать git redate
и вы сможете редактировать все даты в vim из последних 5 коммитов (есть также -c
Опция для того, на сколько коммитов вы хотите вернуться, просто по умолчанию 5). Дайте мне знать, если у вас есть какие-либо вопросы, комментарии или предложения!
Каждый коммит связан с двумя датами, датой коммиттера и датой автора. Вы можете просмотреть эти даты с:
git log --format=fuller
Если вы хотите изменить дату автора и дату принятия последних 6 коммитов, вы можете просто использовать интерактивное перебазирование:
git rebase -i HEAD~6
,
pick c95a4b7 Modification 1
pick 1bc0b44 Modification 2
pick de19ad3 Modification 3
pick c110e7e Modification 4
pick 342256c Modification 5
pick 5108205 Modification 6
# Rebase eadedca..5108205 onto eadedca (6 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
Для всех коммитов, где вы хотите изменить дату, замените pick
от edit
(или просто e
), затем сохраните и выйдите из редактора.
Теперь вы можете изменить каждый коммит, указав дату автора и дату коммиттера в формате ISO-8601:
GIT_COMMITTER_DATE="2017-10-08T09:51:07" git commit --amend --date="2017-10-08T09:51:07"
Первая дата - это дата коммита, вторая - дата автора.
Затем перейдите к следующему коммиту с:
git rebase --continue
Повторяйте процесс, пока вы не исправите все свои коммиты. Проверьте свою прогрессию с git status
,
Как редактировать несколько дат фиксации
Другие ответы не очень удобны для редактирования нескольких дат фиксации. Я вернулся к этому вопросу через несколько лет, чтобы поделиться методикой.
Чтобы изменить даты последних 4 коммитов:
git rebase -i HEAD~4
Отредактируйте rebase следующим образом, вставив exec
строки для изменения дат по мере необходимости:
pick 4ca564e Do something
exec git commit --amend --no-edit --date "1 Oct 2019 12:00:00 PDT"
pick 1670583 Add another thing
exec git commit --amend --no-edit --date "2 Oct 2019 12:00:00 PDT"
pick b54021c Add some tests
exec git commit --amend --no-edit --date "3 Oct 2019 12:00:00 PDT"
pick e8f6653 Fix the broken thing
exec git commit --amend --no-edit --date "4 Oct 2019 12:00:00 PDT"
Прочитав все ответы, я придумал более лаконичный и удобный способ редактирования даты нескольких коммитов одновременно без необходимости интерактивного перенастройки:
git rebase HEAD~4 --exec "git commit --amend --no-edit --date 'now'"
Он изменяет даты как коммиттера, так и автора.
Основываясь на theosp, я написал сценарий под названием git-cdc
(для изменения даты коммита), который я положил в PATH
,
Имя важно: git-xxx
где-нибудь в вашем PATH
позволяет набирать:
git xxx
# here
git cdc ...
Этот скрипт находится в bash, даже в Windows (поскольку Git будет вызывать его из среды msys)
#!/bin/bash
# commit
# date YYYY-mm-dd HH:MM:SS
commit="$1" datecal="$2"
temp_branch="temp-rebasing-branch"
current_branch="$(git rev-parse --abbrev-ref HEAD)"
date_timestamp=$(date -d "$datecal" +%s)
date_r=$(date -R -d "$datecal")
if [[ -z "$commit" ]]; then
exit 0
fi
git checkout -b "$temp_branch" "$commit"
GIT_COMMITTER_DATE="$date_timestamp" GIT_AUTHOR_DATE="$date_timestamp" git commit --amend --no-edit --date "$date_r"
git checkout "$current_branch"
git rebase --autostash --committer-date-is-author-date "$commit" --onto "$temp_branch"
git branch -d "$temp_branch"
С этим вы можете ввести:
git cdc @~ "2014-07-04 20:32:45"
Это сбрасывает дату автора / коммита коммита до HEAD (@~
) к указанной дате.
git cdc @~ "2 days ago"
Это сбрасывает дату автора / коммита коммита до HEAD (@~
) в тот же час, но 2 дня назад.
Ilya Semenov упоминает в комментариях:
Для OS X вы также можете установить GNU
coreutils
(brew install coreutils
), добавьте его вPATH
(PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
) а потом пользуйся2 days ago
"синтаксис.
Чтобы изменить дату автора и дату принятия:
GIT_COMMITTER_DATE="Wed Sep 23 9:40 2015 +0200" git commit --amend --date "Wed Sep 23 9:40 2015 +0200"
Это изменяет дату (метку времени) для последнего коммита
git commit --amend --date "Thu May 28 18:21:46 2015 +0530"
Я создал этот пакет npm, чтобы изменить дату старых коммитов.
https://github.com/bitriddler/git-change-date
Пример использования:
npm install -g git-change-date
cd [your-directory]
git-change-date
Вам будет предложено выбрать коммит, который вы хотите изменить, а затем ввести новую дату.
Если вы хотите изменить коммит по конкретному хешу, запустите git-change-date --hash=[hash]
Информация от июля 2022 года:
Этот работает потрясающе с текущей отметкой времени:
git commit --amend --date=now --no-edit
А этот - с любым форматом даты:
git commit --amend --date="Mon Jul 25 10:37:36 2022 +0300" --no-edit
Если это предыдущий последний коммит.
git rebase -i HEAD~2
git commit --amend --date=now
если вы уже нажали на orgin и можете принудительно использовать:
git push --force
если вы не можете форсировать толчок, и если он толкается, вы не можете изменить коммит!,
Самый простой способ изменить дату последней фиксации
git commit --amend --date="12/31/2021 @ 14:00"
Вот удобный псевдоним, который изменяет время фиксации и автора последнего коммита на время, принятое date --date
:
[alias]
cd = "!d=\"$(date -d \"$1\")\" && shift && GIT_COMMITTER_DATE=\"$d\" \
git commit --amend --date \"$d\""
Использование: git cd <date_arg>
Примеры:
git cd now # update the last commit time to current time
git cd '1 hour ago' # set time to 1 hour ago
Редактировать: вот более автоматизированная версия, которая проверяет, что индекс является чистым (без незафиксированных изменений) и повторно использует последнее сообщение о коммите, или не дает результатов в противном случае (защита от ошибок):
[alias]
cd = "!d=\"$(date -d \"$1\")\" && shift && \
git diff-index --cached --quiet HEAD --ignore-submodules -- && \
GIT_COMMITTER_DATE=\"$d\" git commit --amend -C HEAD --date \"$d\"" \
|| echo >&2 "error: date change failed: index not clean!"
Следующая функция bash изменит время любого коммита в текущей ветви.
Будьте осторожны, чтобы не использовать, если вы уже нажали коммит или если вы используете коммит в другой ветке.
# rewrite_commit_date(commit, date_timestamp)
#
# !! Commit has to be on the current branch, and only on the current branch !!
#
# Usage example:
#
# 1. Set commit 0c935403 date to now:
#
# rewrite_commit_date 0c935403
#
# 2. Set commit 0c935403 date to 1402221655:
#
# rewrite_commit_date 0c935403 1402221655
#
rewrite_commit_date () {
local commit="$1" date_timestamp="$2"
local date temp_branch="temp-rebasing-branch"
local current_branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ -z "$date_timestamp" ]]; then
date="$(date -R)"
else
date="$(date -R --date "@$date_timestamp")"
fi
git checkout -b "$temp_branch" "$commit"
GIT_COMMITTER_DATE="$date" git commit --amend --date "$date"
git checkout "$current_branch"
git rebase "$commit" --onto "$temp_branch"
git branch -d "$temp_branch"
}
Если вы хотите получить точную дату другого коммита (скажем, вы перебазировали отредактированный коммит и хотите, чтобы в нем была дата оригинальной версии перед перебазированием):
git commit --amend --date="$(git show -s --format=%ai a383243)"
Это исправляет дату фиксации HEAD, чтобы быть точно датой фиксации a383243 (включайте больше цифр, если есть неясности). Также появится окно редактора, чтобы вы могли редактировать сообщение о коммите.
Это дата автора, о которой вы обычно заботитесь - см. Другие ответы на дату коммиттера.
Если коммит еще не выдвинут, я могу использовать что-то вроде этого: git commit --amend --date="Ср 25 марта 10:05:44 2020 +0300", после этого git bash открывает редактор с уже примененной датой, поэтому вам нужно просто чтобы сохранить его, набрав в командном режиме редактора VI ":wq", и вы можете нажать его
Установите дату последней фиксации на текущую дату
GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
Установите дату последней фиксации на произвольную дату
GIT_COMMITTER_DATE="Mon 20 Aug 2018 20:19:19 BST" git commit --amend --no-edit --date "Mon 20 Aug 2018 20:19:19 BST"
Установите дату произвольной фиксации на произвольную или текущую дату
Выполните повторное базирование до указанной фиксации и остановитесь для внесения изменений:
git rebase <commit-hash>^ -i
- Заменить
pick
с участиемe
(править) в строке с этим коммитом (первым) - выйти из редактора (ESC, затем
:wq
в VIM) - Либо:
GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
GIT_COMMITTER_DATE="Mon 20 Aug 2018 20:19:19 BST" git commit --amend --no-edit --date "Mon 20 Aug 2018 20:19:19 BST"
Источник:https://codewithhugo.com/change-the-date-of-a-git-commit/
Для обновления даты 5 последних коммитов до текущей даты (этот метод не позволяет обновить первоначальный коммит):
git rebase HEAD~5 --exec "git commit --amend --no-edit --date 'now'"
Для всех коммитов после фиксации 95f5074…15074db2:
git rebase 95f5074…15074db2 --exec "git commit --amend --no-edit --date 'now'"
Для всех коммитов (включая первоначальный коммит):
git rebase --root --exec "git commit --amend --no-edit --date 'now'"
Добавлять
-i
для интерактивного режима.
Бежать
git log --format=fuller --show-signature
для подтверждения изменений.
Бежать
git push -f
обновить удаленный репозиторий (⚠️Опасная зона)
Есть последствия. Например:
- Идентификаторы коммитов изменятся, поэтому вам придется заново создавать теги.
- Вы потеряете оригинальные подписи
- Это будет использовать ваш
.gitconfig
, это означает, что ваш ключ будет использоваться для подписи коммитов (если Git настроен на подписание коммитов)
GIT_COMMITTER_DATE="Sun Nov 20 21:02 2022 +0530" git commit --amend --no-edit --date="Sun Nov 20 21:02 2022 +0530"
git push -f
Работает каждый раз.
Если вы хотите выполнить принятый ответ ( /questions/41786393/kak-mozhno-izmenit-vremennuyu-metku-starogo-kommita-v-git/41786421#41786421) в стандартной командной строке Windows, вам потребуется следующая команда:
git filter-branch -f --env-filter "if [ $GIT_COMMIT = 578e6a450ff5318981367fe1f6f2390ce60ee045 ]; then export GIT_AUTHOR_DATE='2009-10-16T16:00+03:00'; export GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; fi"
Заметки:
- Может быть возможно разделить команду на несколько строк (Windows поддерживает разделение строк с помощью символа "carret")
^
), но мне не удалось. - Вы можете написать даты ISO, сэкономив много времени на поиске правильного дня недели и общего разочарования по поводу порядка элементов.
- Если вы хотите, чтобы дата Author и Committer была одинаковой, вы можете просто сослаться на ранее установленную переменную.
Большое спасибо за сообщение в блоге Колина Свингена. Хотя его код не работал для меня, он помог мне найти правильное решение.
Отредактируйте дату автора и дату фиксации последних 3 коммитов:
git rebase -i HEAD~3 --committer-date-is-author-date --exec "git commit --amend --no-edit --date=now"
В
--exec
команда добавляется после каждой строки в перебазировании, и вы можете выбрать дату автора с помощью
--date=...
, дата коммиттера будет такой же, как и дата автора.
Для тех, кто использует Powershell
git rebase DESIRED_REF^ -i
$commitDateString = "2020-01-22T22:22:22"
$env:GIT_COMMITTER_DATE = $commitDateString
git commit --amend --date $commitDateString
$env:GIT_COMMITTER_DATE = ""
git rebase --continue
Кредит на https://mnaoumov.wordpress.com/2012/09/23/git-change-date-of-commit/
В дополнение к ответу Мэтта Монтага :
Если вам нужно сбросить временную метку на текущее время после команды rebase
git rebase -i HEAD~2
вы можете использовать один из этих вариантов
pick 4ca564e Do something
exec git commit --amend --no-edit --date=now
pick 1670583 Add another thing
exec git commit --amend --no-edit --reset-author
Оба будут работать
Я хотел убедиться, что обновляю комментарии об авторских правах в моем коде ровно в полночь, и я не хотел рисковать с крошечной задержкой с помощью at или cron. Итак, я зафиксировал код, а затем:
GIT_COMMITTER_DATE="Fri Jan 1 00:00:00 2021 +1000" git commit --amend --no-edit --date="Fri Jan 1 00:00:00 2021 +1000"
(Или, возможно, даже установите смещение UTC на 0? Решения…) Теперь я могу нажимать!
Всех с новым годом
Уже есть много хороших ответов, но когда я хочу изменить дату для нескольких коммитов в один день или в один месяц, я не могу найти правильный ответ. Поэтому я создаю новый сценарий для этого с объяснением, надеюсь, он кому-нибудь поможет:
#!/bin/bash
# change GIT_AUTHOR_DATE for commit at Thu Sep 14 13:39:41 2017 +0800
# you can change the data_match to change all commits at any date, one day or one month
# you can also do the same for GIT_COMMITTER_DATE
git filter-branch --force --env-filter '
date_match="^Thu, 14 Sep 2017 13+"
# GIT_AUTHOR_DATE will be @1505367581 +0800, Git internal format
author_data=$GIT_AUTHOR_DATE;
author_data=${author_data#@}
author_data=${author_data% +0800} # author_data is 1505367581
oneday=$((24*60*60))
# author_data_str will be "Thu, 14 Sep 2017 13:39:41 +0800", RFC2822 format
author_data_str=`date -R -d @$author_data`
if [[ $author_data_str =~ $date_match ]];
then
# remove one day from author_data
new_data_sec=$(($author_data-$oneday))
# change to git internal format based on new_data_sec
new_data="@$new_data_sec +0800"
export GIT_AUTHOR_DATE="$new_data"
fi
' --tag-name-filter cat -- --branches --tags
Дата будет изменена:
AuthorDate: Wed Sep 13 13:39:41 2017 +0800
Недавно мне это понадобилось, и я сделал свой собственный скрипт, очень похожий на git-redate.
Однако мои сценарии вносят минимальные изменения и требуют гораздо меньше времени для перезаписи (если вам нужно обновить) многих коммитов, поскольку они делают их все сразу.
На самом деле это также позволяет изменять сообщения фиксации
Объяснение:
Скрипты объединяют кучу bash if-expression, выглядящих так
Вот те, которые изменяют дату фиксации
if [ "$GIT_COMMIT" = "$com_hash" ]; # com is commit
then
export GIT_AUTHOR_DATE="$com_date";
export GIT_COMMITTER_DATE="$com_date";
fi;
Вот те, которые изменяют сообщение коммита:
if [ true = false ]; # impossible
then
: # pass
elif [ "$GIT_COMMIT" = "$com_hash" ];
then
sed 's/.*/$com_msg_esc/g'" # replace content with new content
else
cat - # returns previous content
fi;
И мы нажимаем все обновления, используя
git filter-branch -f \
--env-filter "$UPDATES" \
--msg-filter "$MESSAGES" \
-- "$REV"
(документ находится здесь , человек-фильтр )