コミットのタイムスタンプを変更せずにgit rebase


157

git rebaseコミットのタイムスタンプを保持しながら実行することは理にかなっていますか?

結果は、新しいブランチが必ずしも日付順でコミット日付になるとは限らないということになると私は思います。それは理論的には可能ですか?(例えば、配管コマンドを使用します。ここでは興味があります)

理論的に可能であれば、タイムスタンプを変更せずに実際にリベースを使用することは可能ですか?

たとえば、次のツリーがあるとします。

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

さて、私がリベースoldbranchするmasterと、コミットの日付が1984年2月から2010年6月に変わります。コミットのタイムスタンプが変更されないようにその動作を変更することはできますか?最終的に私はこうして得ます:

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

それはまったく理にかなっていますか?古いコミットに親としてより最近のコミットがある履歴をgitで許可することさえできますか?


3
質問に対する答えが確かに「何もする必要がない-それがデフォルトでどのように機能するかである」というのはファンキーです。しかし、リベース中にコミットを適切な日付順にソートしたいとします(これは、考えればかなり自然なシナリオです)。今、私はそれを達成する方法を見つけることができず、私のqをstackoverflow.com/questions/12270357/really-flatten-a-git-merge
pfalcon

1
Davidは、コミッターの日付をリセットする別のオプションについて言及していますgit rebase --committer-date-is-author-date SHA以下の私の編集済みの回答を
VonC '17

筆者がここで説明した答えを試してみたが、満足のいく形でそれらを適用できなかった同様の質問について広範な答えを書いたところです。
axiac

回答:


149

2014年6月更新:David Fraserコメントで「gitブランチのリベース中にタイムスタンプを変更する」で詳述されている解決策について言及、オプションを使用して--committer-date-is-author-date(2009年1月にコミット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年6月)

非インタラクティブなリベースのために、あなたは試すことができます

git rebase --ignore-date

(このSOの答えから)

これはに渡されgit amます。

 --ignore-date

デフォルトでは、コマンドは電子メールメッセージの日付をコミット作成者の日付として記録し、コミットの作成時刻をコミッターの日付として使用します。
これにより、ユーザーはコミッターの日付と同じ値を使用して、作成者の日付を偽ることができます。

の場合git rebase、このオプションは「--interactiveオプションと互換性がありません」です。

以来古いのタイムスタンプは日付をコミットしますで変更することができます(とgit filter-branch)、私はあなたも、あなたがしたい日付順/必要性をコミット何であなたのGitの歴史を整理することができたとし、将来にそれを設定します!


以下のようオリヴィエは彼の質問に言及し、著者の日付がリベースによって変更されることはありません。プロGitの書籍

  • 作者はもともと作品を書いた人で、
  • 一方、コミッターは最後に作業を適用した人です。

したがって、プロジェクトにパッチを送信し、コアメンバーの1人がパッチを適用すると、両方にクレジットが付与されます。

さらに明確にするために、この例では、Olivierがコメントしています。

これ--ignore-dateは、私が達成しようとしていたこととは正反対です!
つまり、作成者のタイムスタンプを消去して、コミットのタイムスタンプで置き換えます。
したがって、私の質問に対する正しい答えは次のとおり です。デフォルトでは著者のタイムスタンプは実際には変更されない
ため、何もしないでくださいgit rebase



1
コミットする任意の日付について興味深い。ただし、git rebase --ignore-date機能しません。リベースされたコミットの日付を変更します。
Olivier Verdier

@オリビエ:奇妙:インタラクティブなリベースを作成しましたか?著者の日付とコミッターの日付の間で、「正しい」日付を監視しますか?
VonC

1
作成者とコミッターのタイムスタンプの違いであるVonCに感謝します。それがすべてを突然明らかにするものです。質問への回答は投稿に書いていますが、それを反映するように自由に回答を変更してください。
Olivier Verdier 2010年

4
より正確に--ignore-date言う、これは私が達成しようとしていたこととは正反対です!つまり、作成者のタイムスタンプを消去して、コミットのタイムスタンプで置き換えます。したがって、私の質問に対する正しい答えは、git rebaseデフォルトでは著者のタイムスタンプを実際に変更しないため、何もしないことです。
Olivier Verdier 2010年

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。私はLinux上でGitのバージョン1.7.9.5を使用しています(64ビット)
マルクスN.

20
すでに失敗しているが、履歴全体を反復処理したくない場合は、別のアプローチを追加したいと思います。 git rebase --committer-date-is-author-date <base_branch> このようにすると、gitは<base_branch>に適用されたコミットに対してのみコミット日付をリセットします(これはおそらく失敗したときに使用したのと同じブランチ名)。
スピークマン2014年

承認された回答は2016年には機能しませんでしたが、@ speakmanの回答は機能しました。
セオドアR.スミス

2
@speakmanの回答は2016年10月には機能しませんでしたが、Andyは機能しました。
Amedee Van Gasse、2016年

2
これはWindowsでは機能しません。Windows Bashを使用して動作させることができました。
vaindil 2017

33

Von Cの重要な質問は、何が起こっているのかを理解するのに役立ちました。リベースすると、コミッターのタイムスタンプは変更されますが、作者のタイムスタンプは変更されません。だから私の質問は実際には十分正確ではなかった。

答えは、リベースは実際には著者のタイムスタンプを変更しない(それのために何もする必要がない)ことであり、これは私にぴったりです。


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'

これは素晴らしいトリックです!他の回答を使用する場合、1100以上ではなく75のコミットのみを書き換えることができました。
audun 2017年

これは素晴らしいです!元のコミッターも保持するようにスクリプトを変更する方法はありますか?
David DeMar 2018年

@DavidDeMarも同じで、元のメールを記録するようにgit log --prettyを変更し、それに応じてスクリプトを変更するだけです。
weynhamz 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.