あなたは正しいですか?残念ながら、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を強制します。
https://stackoverflow.com/a/45844847/6309は有望です。 – VonC
一般に、構造を保存することは不可能であることに注意してください。例えば、3ca2を5ce5に押しつぶした場合、どうでしょうか?その後、 'stage0'はどこを指すのでしょうか? –
@DavisHerring: 'git filter-branch'と同じようにこれを処理するのが論理的に正しい答えだと思います。古い=>新しいコミットハッシュのマップを作成し、マップエントリに基づいてラベルを置き換えます。 2つのコミットを実行すると、両方の古いコミットが1つの新しいコミットにマップされます。コミットを分割すると、古いコミットが新しいコミットの最初のものにマップされます。既存のリベースコードはこれらのマップの作成には役立ちません。 – torek