Gitでは、このようなことは可能ですか?
master B - C - D
これに?
master A - B - C - D
Git を使用した既存のプロジェクトがあり、すべてうまくいきました。しかし、そのプロジェクトの古いバージョンを見つけたので、同じレポにコミットしたいのですが、それを A にして、そのプロジェクトの最も古いバージョンのように見せます。Gitでこれを行うことは可能ですか? または他の回避策はありますか?
Gitでは、このようなことは可能ですか?
master B - C - D
これに?
master A - B - C - D
Git を使用した既存のプロジェクトがあり、すべてうまくいきました。しかし、そのプロジェクトの古いバージョンを見つけたので、同じレポにコミットしたいのですが、それを A にして、そのプロジェクトの最も古いバージョンのように見せます。Gitでこれを行うことは可能ですか? または他の回避策はありますか?
はい、かなり簡単に実行できますが、標準の警告から始めてB-C-D
、B'-C'-D'
. それであなたの罰金を仮定すると...
まず、git が一連のコミットとして編成され、それぞれがその親へのポインターを持っていることを理解することから始めます。このようにして、コミットのツリーが作成されます。
tree 1: B - C - D
あなたがしたいことは、最初のコミットの前に何かを追加することであり、最初のコミットの前に対処することは何もないため、これを行うために新しいツリーを作成する必要があります。
新しいツリーを作成するには、空のコミットから始めます。リポジトリの最初のコミットとして空のコミットを使用すると、このようなことが容易になります。これは、次のコマンドで実行されます (後で参照するために番号が追加されています)。
git checkout --orphan new-branch (1)
git rm -r --force --cached . (2)
git clean -fd (3)
git clean -fd (3a)
git commit --allow-empty -m 'Initialize' (4)
これにより、他のブランチに接続されていない新しいブランチが作成されます (1)。これにより、作業ディレクトリ内のすべてのファイルがキャッシュされ、コミットの準備が整います。これらのファイルをコミットしたくないので、(2) それらをキャッシュから削除します。while (3) ディレクトリからそれらを削除します。無視されたファイルは消去されませんが、.gitignore ファイルは消去されるため、2 回消去する必要がある場合があります。ファイルは再度消去する必要があります。
最後に、(4) このブランチの最初のコミットとして空のコミットを作成します。--allow-empty
引数はこれを可能にします -- そしてどんなメッセージもそうします。
ここで、以前のバージョンのプロジェクトからすべてのファイルを追加し、A
コミットします。
git add .
git commit -m 'A'
------------------
tree 1: B - C - D
tree 2: A
に進む準備ができましB-C-D
たA
。がオンの間new-branch
、このコマンドはそれらを移動します。
git rebase -i --onto new-branch --root D
これは をチェックアウトD
し、ツリーをルートに戻し (巻き戻し)、B
各コミットを順番に移動しますA
- に戻るまで、各ステップで新しいコミットを作成しD
ます。 注: ここでマージの競合が発生する可能性が高いため、それらを処理する準備をしてください。
完了すると、ツリーは次のようになります
tree 1: <empty> <-- this will be garbage collected in time
tree 2: A - B' - C' - D'
この時点で、リモート リポジトリにプッシュ バックします。プッシュを強制する必要があります。
git push --force <remote> <local-branch>:<remote-branch>
これにより、リモート ブランチが上書きされます。これが必要なものであることを確認してください。
それだけです。リポジトリの唯一のコピーで作業しないことを忘れないでください。そうすれば、再クローンして、問題が発生した場合に再試行できます。それ以外は、実際のリポジトリgit rebase ...
の複雑さに応じて、何が起こっているのか、そして遭遇する可能性のある癖についてよく知っているように、読んでおくことをお勧めします。B-C-D
Aを新しいコミットとして追加し、B()の前にインタラクティブにコミットをリベースして、コミットを希望どおりrebase -i B~1
に並べ替えることができますか?
はい、注意事項があります。あなたがから始めるとしましょう:
B - C - D
結果は次のようになります。
あいうえお'
「プライム」マーカーに注意してください。B' は B と同じツリー(コンテンツ) を持ちますが、親が異なるため、異なる SHA-1 ハッシュを持ちます。
これを行う最も簡単な方法は、移植片を使用することです。A と B の両方を含むリポジトリを作成します。
あ B - C - D
それらが互いに接続されていないことに注意してください。それらを「グラフト」( Wiki ページ) で相互に接続すると、A が B の親になります...
あ \ ... \ B - C - D
移植は一時的なものなので、点線を使用しました。グラフトは、編集.git/info/grafts
および書き込みによって作成されます。
<Bのハッシュ> <Aのハッシュ>
グラフトは次のコマンドで永続化されます:
git filter-branch --tag-name-filter cat -- --all
これにより、グラフが次のように変更されます。
あいうえお'
永続化したら、grafts ファイルを削除します。
通常の警告が適用されます。履歴を書き換えているため、リポジトリをプルした人はgit reset
、ローカルの変更がない限り、 を使用する必要があります。
要するに、違います。
Gitの各コミットはハッシュで表され、「親」コミットはハッシュ生成の要素の1つです。
したがって、Bの親を変更すると、BはBではなくなります(つまり、ハッシュは同じではなくなります)
リベースを使用してこれを行うこともできます。最初にAを作成し、AでB、C、D ...をリベースします。ただし、前に述べたように、ハッシュは同じではなくなります。それがあなたにとって大丈夫なら、これを先に進めてください:)