189

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

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

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

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

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

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

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

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

4

6 に答える 6

190

2014 年 6 月の更新: David Fraserはコメントで、オプション(2009 年 1 月にコミット 3f01ad6で最初に導入された) を使用して、「 git ブランチのリベース中にタイムスタンプを変更する」でも詳述されているソリューションについて言及しています。--committer-date-is-author-date

この--committer-date-is-author-dateオプションは作成者のタイムスタンプを残し、コミッターのタイムスタンプを元の作成者のタイムスタンプと同じに設定するように見えることに注意してください。これは、OP Olivier Verdierが望んでいたことです。

正しい日付の最後のコミットを見つけて、次のことを行いました。

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

参照git am:

--committer-date-is-author-date

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

注: Git 2.29 (2020 年第 4 四半期) では、git rebase--committer-date-is-author-dateまたは 以下--ignore-dateでも動作します。

  • 対話型リベース ( rebase -i/ rebase --interactive)
  • ルートコミット ( git rebase --root)

「 git ブランチのリベース中にタイムスタンプを変更する」を参照してください。


(元の回答、2012 年 6 月)

あなたは試すことができます非インタラクティブリベース
(上記を参照してください: Git 2.29、2020 年第 4 四半期では、インタラクティブなリベースでも機能します)

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


DylanYoungがコメントに追加したように、「git rebase 中にハッシュによって競合するコミットを識別するにはどうすればよいですか?」を使用して:

SEQUENCE_EDITOR変数と rebase interactiveを使用すると、現在のリストをループして、の各コミットの前に を元のコミットの日付にtodo設定するコマンドを追加するだけです。GIT_COMMITER_DATEtodo

最初に元のコミットのリストがあるため (それを見つけるために git 内部にハックする必要はありません)、少し面倒ではありませんが、リスト全体を一度に処理する必要があるため、もう少し手間がかかります。–</p>

元のコミットを特定できたら、次のようなことができます。

git rebase -x 'GIT_COMMITTER_DATE="git show -s --format=%ci ``get_current_commit``" git commit --amend --no-edit
于 2010-06-04T18:04:43.617 に答える
134

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

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

于 2012-06-24T16:41:13.360 に答える
39

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

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

于 2011-06-14T08:31:35.520 に答える
19

デフォルトでは、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'
于 2013-10-22T16:06:41.630 に答える