Git rebase без изменения временных меток фиксации
Имеет ли смысл выполнять git rebase
при сохранении временных меток фиксации?
Я считаю, что последствием будет то, что новый филиал не обязательно будет фиксировать даты в хронологическом порядке. Теоретически это возможно? (например, используя команды сантехники, просто любопытно здесь)
Если теоретически это возможно, то можно ли на практике с rebase не менять временные метки?
Например, предположим, что у меня есть следующее дерево:
master <jun 2010>
|
:
:
: oldbranch <feb 1984>
: /
oldcommit <jan 1984>
Теперь, если я переустанавливаю oldbranch
на master
, дата фиксации изменяется с feb 1984 до jun 2010. Можно ли изменить это поведение так, чтобы метка фиксации не была изменена? В итоге я получаю:
oldbranch <feb 1984>
/
master <jun 2010>
|
:
Будет ли это иметь смысл? Разрешено ли даже в git иметь историю, в которой у старого фиксатора есть более недавняя фиксация в качестве родителя?
Ответы
Ответ 1
Решающий вопрос Von C помог мне понять, что происходит: когда ваш rebase, временная метка коммиттера изменяется, но не метка времени автора, которая внезапно имеет смысл. Поэтому мой вопрос был на самом деле недостаточно точным.
Ответ заключается в том, что rebase на самом деле не изменяет метки времени автора (вам не нужно ничего делать для этого), что идеально подходит мне.
Ответ 2
Обновление в июне 2014 года: Дэвид Фрейзер упоминает в комментариях решение, также подробно описанное в "Изменить временные метки при перезагрузке git branch", используя опцию --committer-date-is-author-date
(введена первоначально в январе 2009 года в совершить 3f01ad6
Обратите внимание, что параметр --committer-date-is-author-date
, по-видимому, оставляет метку времени автора и устанавливает временную метку коммиттера равной той же самой отметке времени автора, что и OP Olivier Verdier.
Я нашел последнюю фиксацию с правильной датой и сделал:
git rebase --committer-date-is-author-date SHA
См. git am
:
--committer-date-is-author-date
По умолчанию команда записывает дату из сообщения электронной почты в качестве даты фиксации фиксации и использует время создания фиксации как дату коммиттера.
Это позволяет пользователю лгать о дате коммиттера, используя то же значение, что и дата автора.
(Оригинальный ответ, июнь 2012 г.)
Вы можете попробовать, для неинтерактивной переадресации
git rebase --ignore-date
(из этого SO ответ)
Это передается git am
, в котором говорится:
--ignore-date
По умолчанию команда записывает дату из сообщения электронной почты в качестве даты фиксации фиксации и использует время создания фиксации как дату коммиттера.
Это позволяет пользователю лгать о дате автора, используя то же значение, что и дата коммиттера.
Для git rebase
эта опция "Несовместима с опцией -interactive".
Поскольку вы можете по желанию изменить временную метку старой даты фиксации (с git filter-branch
), я полагаю, вы можете организовать свою историю git с любым заказом даты фиксации, который вы хотите/нуждаетесь, даже установить его в будущее!.
Как Olivier упоминает в своем вопросе, дата автора никогда не изменяется с помощью rebase;
Из Pro git Книга:
- Автор - это тот, кто изначально написал произведение,
- тогда как коммиттер - это тот, кто последний раз применял эту работу.
Итак, если вы отправляете патч к проекту, и один из основных членов применяет патч, вы получаете кредит.
Чтобы быть более ясным, в этом случае, как пишет Оливье:
--ignore-date
делает противоположное тому, что я пытался достичь!
А именно, он удаляет метку времени автора и заменяет их метками фиксации!
Поэтому правильный ответ на мой вопрос:
Не делайте ничего, поскольку git rebase
по умолчанию не меняет метки времени авторов.
Ответ 3
Если вы уже набрали даты фиксации (возможно, с rebase) и хотите, чтобы reset их соответствовали датам авторов, вы можете запустить:
git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE'
Ответ 4
По умолчанию, git rebase будет устанавливать метку времени коммитера на время, когда
создается новая фиксация, но сохраняйте временную метку автора неповрежденной. Большая часть времени,
это желаемое поведение, но в некоторых сценариях мы не хотим менять
временная метка commiter. Как мы можем это сделать? Ну, вот
трюк, который я обычно делаю.
Во-первых, убедитесь, что каждый из коммитов, которые вы собираетесь переупаковать, имеет уникальную
фиксировать сообщение и метку времени автора (это то, где трюк нуждается в улучшениях, в настоящее время он удовлетворяет мои потребности).
Перед перезагрузкой запишите метку времени коммитера, метку времени автора и сообщение фиксации всех коммитов, которые будут переустановлены в файл.
#NOTE: BASE is the commit where your rebase begins
git log --pretty='%ct %at %s' BASE..HEAD > hashlog
Затем дайте фактическую перезагрузку.
Наконец, мы заменяем временную метку коммиттера той, что записана в файле, если сообщение фиксации совпадает с использованием git filter-branch
.
git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%at %s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_COMMITTER_DATE=$__date || cat'
Если что-то пойдет не так, просто проверьте git reflog
или все refs/original/
refs.
Furthormore, вы можете сделать то же самое с меткой времени автора.
Например, если временная метка автора некоторых коммитов не соответствует порядку и
без переупорядочения этих коммитов, мы просто хотим, чтобы метка времени автора отображалась в
порядок, то следующие команды помогут.
git log --pretty='%at %s' COMMIT1..COMMIT2 > hashlog
join -1 1 -2 1 <(cat hashlog | cut -f 1 | sort -nr | awk '{ print NR" "$1 }') <(cat hashlog | awk '{ print NR" "$0 }') | cut -d" " -f2,4- > hashlog_
mv hashlog_ hashlog
git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_AUTHOR_DATE=$__date || cat'