git rebase без зміни часових позначок фіксації


157

Чи було б доцільно виконувати git rebase, зберігаючи часові позначки фіксації?

Я вважаю, що наслідком цього є те, що нова філія не обов'язково має дати хронологічного введення. Чи теоретично це взагалі можливо? (наприклад, використання сантехнічних команд; тут просто цікаво)

Якщо це теоретично можливо, то чи можливо на практиці з базою даних не змінювати часові позначки?

Наприклад, припустимо, у мене є таке дерево:

master <jun 2010>
  |
  :
  :
  :     oldbranch <feb 1984>
  :     /
oldcommit <jan 1984>

Тепер, якщо я перебазуватися oldbranchна master, дата фіксації змін з лютого 1984 по червень 2010 Чи можна змінити цю поведінку так , що фіксація мітки часу не змінюється? Зрештою, я отримав би таким чином:

      oldbranch <feb 1984>
      /
 master <jun 2010>
    |
    :

Це взагалі має сенс? Чи дозволяється навіть у git мати історію, коли стара фіксація має більш пізню версію як батьків?


3
Дивно, що відповідь на питання справді "вам нічого не потрібно робити - ось як це працює за замовчуванням". Але тепер припустимо, що ви хочете, щоб класифікація сортувалась у належному порядку, виконуючи перезавантаження (що є цілком природним сценарієм, якщо ви думаєте про це). Тепер, я не зміг знайти , як домогтися цього, і відправив свій д в stackoverflow.com/questions/12270357/really-flatten-a-git-merge
pfalcon

1
Давид згадує ще один варіант для скидання зафіксував дати: git rebase --committer-date-is-author-date SHA. Дивіться мою відредаговану відповідь нижче
VonC

Я просто написав обширну відповідь на подібне запитання , автор якого спробував відповіді, пояснені тут, і не зміг їх застосувати задовільно.
аксіак

Відповіді:


149

Оновлення червня 2014 року: Девід Фрейзер в коментарях згадує рішення, також детальне в розділі " Змінити часові позначки під час перезавантаження гіт-гілки ", використовуючи опцію --committer-date-is-author-date(введена спочатку в січні 2009 року в комітеті 3f01ad6

Зауважте, що --committer-date-is-author-dateваріант, здається, залишає авторську часову марку та встановлює часову позначку читця, що відповідає оригінальній авторській часовій позначці, чого і хотів ОП Олів'є Верд'є .

Я знайшов останню прихильність із правильною датою і зробив:

git rebase --committer-date-is-author-date SHA

Дивіться git am:

--committer-date-is-author-date

За замовчуванням команда записує дату з повідомлення електронної пошти як дату автора фіксації та використовує час створення фіксації як дату виконання.
Це дозволяє користувачеві брехати про дату вступу, використовуючи те саме значення, що й дата автора .


(Оригінальна відповідь, червень 2012 р.)

Ви можете спробувати, для неінтерактивному Rebase

git rebase --ignore-date

(з цієї відповіді ТАК )

Це передано git am, у якому згадується:

 --ignore-date

За замовчуванням команда записує дату з повідомлення електронної пошти як дату автора фіксації та використовує час створення фіксації як дату виконання.
Це дозволяє користувачеві брехати про дату автора, використовуючи те саме значення, що й дата введення.

Тому що git rebaseцей параметр "Не сумісний із - інтерактивним варіантом".

Оскільки ви можете за бажанням змінити часову позначку старої дати фіксаціїgit filter-branch), я вважаю, що ви можете організувати свою історію Git з будь-яким порядком дати фіксації, який ви хочете / потребуєте, навіть встановити його на майбутнє! .


Як згадує Олів'є у своєму питанні, дата автора ніколи не змінюється за допомогою рефералу;
З книги Pro Git :

  • Автор - людина, яка спочатку написала твір,
  • тоді як виконавцем є особа, яка востаннє застосувала цю роботу.

Отже, якщо ви надсилаєте патч до проекту, і один із основних учасників застосовує патч, ви обидва отримуєте кредит.

Щоб бути надзвичайно зрозумілим, в цьому випадку, як коментує Олів'є:

це --ignore-dateробить протилежне тому, що я намагався досягти !
А саме, вона стирає авторську мітку часу та замінює їх часовими позначками.
Тож правильна відповідь на моє запитання:
Не робіть нічого, оскільки git rebase насправді не змінюють часові позначки авторів за замовчуванням.



1
Цікаво про довільні дати вчинення. Однак git rebase --ignore-dateне працює. Він змінює дати знижених комісій.
Олів'є Верд'є,

@Olivier: дивно: ти зробив нон -interactive перебазування? А між датою автора та датою вступу, чи ми впевнені, що ми відстежуємо "правильну" дату?
VonC

1
Дякую VonC, різниця між часовою позначкою автора та виконавця, саме це робить все раптом зрозумілим. Я написав відповідь на своє запитання у своєму дописі, але сміливо адаптуйте свою відповідь, щоб це відобразити.
Олів'є Верд'є

4
Якщо бути точнішим: це --ignore-dateробить протилежне тому, що я намагався досягти! А саме, вона стирає авторську мітку часу та замінює їх часовими позначками. Тож правильна відповідь на моє запитання: нічого не робіть, оскільки git rebaseнасправді не змінюють часові позначки авторів за замовчуванням.
Олів'є Верд'є,

5
Зверніть увагу , що --committer-date-is-author-dateваріант , здається, залишає автору мітку часу, і встановити комміттер мітку часу , щоб бути таким же , як оригінальний автор мітки часу, що і хотів Олів'є ...
Девід Фрейзер

118

Якщо ви вже накрутили дати фіксації (можливо, з перезавантаженням) і хочете відновити їх до відповідних авторських дат, можете запустити:

git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE'


1
Я просто спробував це, але ефекту немає. Я отримав на наступні результати: WARNING: Ref 'refs/heads/master' is unchanged. Я використовую git версії 1.7.9.5 в Linux (64 біт)
Markus N.

20
Я хотів би додати інший підхід, якщо ви вже викрутили, але не хочете повторювати всю історію: git rebase --committer-date-is-author-date <base_branch> Таким чином, git скидає дату фіксації лише для комісій, застосованих у <base_branch> (що, мабуть, є та сама назва гілки, яку ви використовували, коли ви викрутили).
виступаючий

У 2016 році прийнята відповідь не спрацювала, але відповідь @ speakman зробила!
Теодор Р. Сміт

2
@ відповідь говорителя не працювала в жовтні 2016 року, але Енді зробив!
Амеді Ван Гассе

2
Це не працює в Windows. Мені вдалося змусити його працювати за допомогою Windows Bash.
vaindil

33

Важливе питання Фон С допомогло мені зрозуміти, що відбувається: коли ваша база даних, часова мітка комітента змінюється, але не часова мітка автора , що раптом все має сенс. Тож моє запитання насправді було недостатньо точним.

Відповідь полягає в тому, що база даних насправді не змінює часові позначки автора (для цього не потрібно нічого робити), що мені ідеально підходить.


3
+1 - у мене є псевдонім git ( coderwall.com/p/euwpig/a-better-git-log ), який, очевидно, використовує позначку часу комітента, що мене бентежило. Gitk та git log показують часову позначку автора.
1615903

15

За замовчуванням git rebase встановлює часову позначку виконавця на час створення нової комісії, але зберігає часову марку автора недоторканою. Здебільшого це бажана поведінка, але в деяких сценаріях ми також не бажаємо змінювати часові позначки комітента. Як ми можемо це досягти? Ну ось ось трюк, який я зазвичай роблю.

По-перше, переконайтеся, що кожен із зобов’язань, які ви збираєтеся перезавантажити, має унікальне повідомлення про фіксацію та часову позначку автора (саме тут потрібна поліпшення трюку, хоча він відповідає моїм потребам).

Перед початком ребазації запишіть часову позначку виконавця, авторську часову марку та повідомлення про всі зобов'язання, які будуть повторно передані у файл.

#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/знижки.

Фурторморе, ви можете зробити аналогічну до авторської мітки часу.

Наприклад, якщо відмітка часу автора деяких комісій вийшла з ладу, і не переставляючи ці комірки, ми просто хочемо, щоб авторська мітка часу відображалася в порядку, тоді допоможуть наступні команди.

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'

Це чудова хитрість! Це дозволило мені лише переписати 75 команд замість 1100+ із використання інших відповідей.
аудіун

Це фантастично! Чи є спосіб змінити скрипт, щоб також зберегти оригінальний фіксатор?
Девід Демар

@DavidDeMar має бути те саме, просто змініть журнал git --pretty для запису оригінальної електронної пошти та відповідно змініть скрипт.
weynhamz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.