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'