2017-12-16 6 views
1

私はこの歴史を開始した場合:リベースを使用して同じ履歴を共有するブランチをどのように保つか?

* 505421e - (HEAD -> stage4) go to stage 4 
* 307978f - (stage3) go to stage 3 
* d8ab213 - steb b 
* 49cbef9 - (stage2) step a 
* 6e4a2ed - (stage1) go to stage 1 
* 3ca2d7d - do something 
* 5ce596d - (stage0) go to stage 0 
* 0c8487b - foo 
* ccfb7c9 - bar 

そして、私はその後、枝が stage0–stage3は、もはや同じ stage4として歴史をコミットしなければならない、と更新 fooがコミットしていないだろう、 fooがコミット変更するために git rebase -i ccfb7c9しません。彼らに同じ歴史を持たせるにはどうすればいいですか?

+0

https://stackoverflow.com/a/45844847/6309は有望です。 – VonC

+0

一般に、構造を保存することは不可能であることに注意してください。例えば、3ca2を5ce5に押しつぶした場合、どうでしょうか?その後、 'stage0'はどこを指すのでしょうか? –

+0

@DavisHerring: 'git filter-branch'と同じようにこれを処理するのが論理的に正しい答えだと思います。古い=>新しいコミットハッシュのマップを作成し、マップエントリに基づいてラベルを置き換えます。 2つのコミットを実行すると、両方の古いコミットが1つの新しいコミットにマップされます。コミットを分割すると、古いコミットが新しいコミットの最初のものにマップされます。既存のリベースコードはこれらのマップの作成には役立ちません。 – torek

答えて

1

あなたは正しいですか?残念ながら、Gitには "正しい方法"を行うためのものは何も組み込まれていません。 という特別な定義がありますが、ある時点でそれを行うプログラムを作成し始めていますが、はここではと定義するのがやや難しいです。それはすべての奇妙なコーナーのケースでは難しすぎて、私はそれを断念した。

かのように、ここでの基本的な問題は、(インタラクティブリベースはあなたが道に沿っていくつかの追加の変更を加えるせると)git cherry-pickにより、によってgit rebase作品はコミットをコピーすることです。 新しいコピーには、新しい、異なるハッシュIDがあります。 コピーが作成されたら、Gitはの1つをブランチ名-の最新のブランチに置き換えます。これは最後にコピーされたコミットまでgit rebaseでした。その中で

  • 0c8487b - foo
  • 5ce596d - (stage0) go to stage 0
  • 3ca2d7d - do something
  • ...
  • 505421e - (HEAD -> stage4) go to stage 4

:つまり

、この場合には、あなたはGitのコピーを持っています注文(最初から最後まで)、一度に1つずつ。最初のステップではに変更します。何かを変更する限り、新しいコミットには新しい、異なるハッシュID(cccccc1など)が得られるように、実際には何も関係ありません。 「新しいコミット1」と呼ぶことができます)。この新しいコミットの親コミットはbarと表示されているコミットであるccfb7c9であるため、新しい履歴はその時点の古い履歴に再結合します。

次に、Gitは2番目のコミット5ce596d - (stage0) go to stage 0をコピーします。これは、たとえばcccccc2になります。 cccccc2の親はcccccc1であり、これだけが異なるコミットであることを強制するためには5ce596dとは十分に異なります。 Gitは8つのコミットをすべてコピーし、最後のものはおそらくcccccc8になります。 Gitはstage4という名前を変更して、コミットの名前をcccccc8に変更します。

Gitが名前stage4で見つけたコミットから始めて履歴を見ると、という新しいの履歴が表示されます。しかし、Gitは他のの名前を変更していません。例えば、stage3はコミット307978fを依然として識別しますが、stage0は依然としてコミット5ce596dを識別します。したがって、のいずれかの名前から開始して履歴を見ると、元の一連のコミットが表示されます。

あなたが必要とするのは、各ラベルを元のハッシュから新しいハッシュに移動させることです。この問題は、これらすべてのものを特定することによってもたらされます。のラベルはに移動する必要がありますか? (古いコミットを意図的に保持する人もあれば、移動させる人もいればいいかもしれません)。インタラクティブ・リベース中に、コミットを分割して他のものを組み合わせることを選択した場合はどうなりますか?

簡潔で強力なソリューションは、変更したい名前を手動で強制して、新しいコミットを指すようにすることです。

git branch -f stage0 newhash0 
git branch -f stage1 newhash1 
git branch -f stage2 newhash2 
git branch -f stage3 newhash3 

をすれば完了です:git log --all --decorate --oneline --graphを実行し、それぞれの名前のために古いものと新しいコミットIDを書き留め、その後、実行します。または、これらのブランチ名の一部を完全に削除してください。これは、stage4(自動的に移動する)から始まり、後方に向かってコミットを見つけることができるからです。名前だけの「コミットに生のポインタ」よりも多くの意味を持つように


私が好きな定義は、構造化ブランチ名を必要とします。この構造化のフォームも同様に困難です。名前階層を使用するか、ブランチ名を「スーパーブランチ」にグループ化するためにgit configのエントリが必要ですか?

git rebaseコマンドの一部は、実際にはgit cherry-pickです。一部のコマンドでは実行されません。対話型のリベースは、実際にgit cherry-pickを実行して、git commit --amendなどのトリッキーな項目と一緒に実行するケースの1つです。 「コピー」は、同一-あなたは同じハッシュIDを巻くビットの元のビットと100%同一であるかのように、任意のGitのオブジェクトのハッシュIDが厳しく、その内容によって決定される

、すなわち、あなたは単にオリジナルを再利用します。しかし、変更を行うとすぐに、シーケンス内のコミットのハッシュIDが変更され、すべての "下流"(子)コミットが異なる親のハッシュIDを強制します。

関連する問題