web-dev-qa-db-ja.com

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

git rebaseコミットタイムスタンプを保持しながら?

結果として、新しいブランチのコミット日付は必ずしも時間順になるとは限らないと思います。それは理論的にまったく可能ですか? (例:配管コマンドの使用;ここで好奇心が強い)

理論的に可能な場合、実際にはタイムスタンプを変更せずにリベースを使用できますか?

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

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

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

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

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

139
Olivier Verdier

Von Cの重大な質問は、何が起こっているのかを理解するのに役立ちました:リベースすると、committer'sタイムスタンプが変更されますが、author'sタイムスタンプは突然変更されます。したがって、私の質問は実際には十分に正確ではありませんでした。

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

30
Olivier Verdier

2014年6月更新: David Fraser がコメントの に言及しているgitブランチのリベース中にタイムスタンプを変更 "、オプション_--committer-date-is-author-date_を使用(2009年1月に commit 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を整理できると思います希望する/必要なコミット日付順の履歴、 未来に設定することもできます!


Olivier が彼の質問で言及しているように、著者の日付はリベースによって決して変更されません。
Pro Git Book から:

  • 著者は元々その作品を書いた人であり、
  • 一方、コミッターは作業を最後に適用した人です。

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

この場合、Olivierがコメントしているように、さらに明確にするために:

_--ignore-date_は、私が達成しようとしていたことの反対です
つまり、作成者のタイムスタンプを消去し、コミットのタイムスタンプに置き換えます!
だから私の質問に対する正しい答えは:
デフォルトでは_git rebase_は作成者のタイムスタンプを変更しないため、何もしないでください。


131
VonC

コミット日を既に台無しにして(おそらくリベースを使用)、対応する作成者の日付にリセットする場合は、次を実行できます。

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

114
Andy

デフォルトでは、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'
14
weynhamz