私の機能ブランチには、約50のコミットがあります。最初のコミットでは、後続のコミットで大幅に変更されるファイルを作成しました。私は今、そのファイルを別のディレクトリに保存する方が良いことを理解しているので、最初のコミットに戻って最初から適切な場所に作成して、履歴をきれいに保ちたいと思います。最初のコミットを編集してファイルを移動することでインタラクティブなリベースでこれを行うことができますが、そのファイルに触れる以降のコミットはすべて手動で解決する必要がある競合を生成します。ファイルが移動されたことをすべてのコミットに伝える方法はありますか?そのため、適切な場所で変更を自動的に適用しますか?
TL;DR
git filter-branch
を使用する 。--index-filter
を使用できます スピードのためですが、これは使いにくいです。わずか50件のコミットで、--tree-filter
を使用します はるかに遅いですが、はるかに使いやすいです:通常、これはコピー 元のリポジトリの(クローン)フィルターブランチを簡単に変更でき、回復します それから、コピーを削除して最初からやり直すことです。
動作したら、すべての
長いですrefs/original/
を削除しますgit filter-branch
で説明されている名前 ドキュメンテーション。リポジトリーは最終的にデブロートされます(フィルターブランチのサイズは一時的におよそ2倍になります)。Gitでの履歴は、コミットです。履歴を変更するには、古いコミット(古い履歴を提供する)を新しい異なるコミット(新しい履歴を提供する)にコピーする必要があります。だからあなたの目標は、すべての50のようなコミットを同じものに置き換えることですを除く ファイルが他のパスに再配置されること。
あなたが言ったように、あなたはできる インタラクティブなリベースでこれを行いますが、それは苦痛です:リベースは、コピーする各コミットを変更セットに変換し(そのコミットをその親と比較して、変更内容を確認することにより)、既存のコミットに同じ変更を適用することで動作します。
かなり重いコマンド
git filter-branch
があります 、その目的は、ある種のコミット修飾子を適用しながらコミットをコピーすることです。本質的に非常に遅いため、多くのオプションがあります。しかし基本的には、次のもので構成されます。操作対象のすべてのコミットを(ハッシュIDで)リストします。あなたの場合、それは単に「すべてのコミット」です。また、古いハッシュID→新しいハッシュIDの空のマップを作成します。
次に、ルートの最も古い(最も古い/最も古い)コミットから開始します。
コミットを一時的な作業領域に抽出します。
さまざまなフィルターのそれぞれを適用します。
結果から新しいコミットを作成します。ハッシュマップを使用して親IDをマッピングし、新しいコミットが以前にコピーされた新しいコミットを指すようにします。これにより、コマンドに新しいコミットのハッシュIDが与えられます。
古いコミットハッシュ→新しいコミットハッシュからマップにエントリを追加します。
最後に、コミットされるすべてのコミットについて上記を実行した後、すべてのループをループします参照 変更するように指示します(主にブランチ名ですが、
--tag-name-filter
を使用する場合はタグ名も ):refs/whatever
から元の参照の名前を変更しますrefs/original/refs/whatever
へ 。新しい
refs/whatever
を作成する マップで見つかった新しいハッシュを使用します。このプロセスの最後に、元のすべてのコミットがあります(
refs/original
それらを参照するため)とすべての新しいコミット(ブランチ名を使用)。ブランチ名が1つしかなく(タグがない)場合、指定する必要がある唯一の名前はこの1つのブランチ名で、おそらく
master
、しかし--all
Gitにすべての参照を参照するよう指示し、--tag-name-filter cat
タグを更新するときにタグ名に加えるべき変更は、変更を加えないことであることをGitに伝えます。ザ・
--tree-filter
git filter-branch
に指示します ステップ1(コミットの抽出)では、git filter-branch
の一時ディレクトリに対して完全かつ完全な抽出を実行する必要がある 独自に構築します。 (他のフィルターオプションは、非常に高速な一時インデックスへの抽出のみのトリックで逃げようとします。)tree-filter
に指定するコマンド この一時ディレクトリで実行されるため、ファイルの名前を変更するだけでよい場合は、次のコマンドを実行します。十分です(Unix/Linuxのようなシステムを想定しています)。