5

私はこの質問を認識していますが、それを私の現在の状況にマッピングする方法がわかりません. (リベースは怖い、リベースを元に戻すのは二重に怖い!)

マスターのいくつかの異なる機能ブランチから始めました。

master    x-x-x-x-x-x-x-x-x-x
             \       \    \
FeatureA      1-2-3   \    \
FeatureB               A-B  \
FeatureC                     X-Y-Z

それらをすべてマージして、マスターの上部にマージする前に機能することを確認したかったので、次のことを行いました。

git checkout FeatureB
git rebase FeatureA
git mergetool //etc
git rebase --continue

それで

git checkout FeatureC
git rebase FeatureB
git mergetool //hack hack
git rebase --continue

それは私を残します

master    x-x-x-x-x-x-x-x-x-x
             \
FeatureA      1-2-3 
                   \
FeatureB            A'-B'
                         \ 
FeatureC                  X'-Y'-Z'

次に、適切にコンパイルされなかったいくつかのビットを修正し、機能セット全体を許容可能な状態にしました。

master    x-x-x-x-x-x-x-x-x-x
             \
FeatureA      1-2-3 
                   \
FeatureB            A'-B'
                         \ 
FeatureC                  X'-Y'-Z'-W

問題は、FeatureA の準備ができていないと同僚が言うことです。

すべての作業を保持しながら、FeatureC を FeatureB にリベースできる状況に戻す方法はありますか?

4

3 に答える 3

5

これは、コメントに基づいて、答えが何であるかについての私の理解です:

リベースを実行すると、現在のブランチのコミットは「元に戻され」、次に「再適用」されますが、実際には元に戻されず、「記憶」*され、新しいIDで再適用されます。でgit reflog show FeatureB、私は次のようなものを取得します:

7832f89 FeatureB@{0} rebase finished: refs/heads/FeatureB onto f4df3
efd3fed FeatureB@{1} commit: B
f3f3d43 FeatureB@{2} commit: A
2f32fed FeatureB@{3} branch: Created from HEAD

したがって、@ Jefromiが言ったように、オリジナルはまだそこにあります(reflogのAおよびBコミットのSHAは、A'およびB'に対応するgitlogのSHAと同じではありません)。

同様に、git reflog show FeatureCこのように見えます

32873ef FeatureC@{0} commit: W
17dafb3 FeatureC@{1} rebase finished: refs/heads/FeatureC onto 89289fe
893eb78 FeatureC@{2} commit: Z
a78b873 FeatureC@{3} commit: Y
e78b873 FeatureC@{4} commit: X
378cbe3 FeatureC@{5} branch: Created from HEAD

繰り返しますが、元のZ、Y、Xコミットはまだあります

したがって、私の問題の解決策は、マスターのHEADから新しいブランチを作成しFeaturesBC(たとえば)、コミットをチェリーピックしてFeatureB {2&1}、次にFeatureC {4、3、2}、そして(おそらく)W:

git checkout master
git checkout -b FeaturesBC
git cherry-pick f3f3d43 
git cherry-pick efd3fed 
//etc...

(うまくいったようです。同じマージをいくつかやり直さなければなりませんでしたが、それほど悪くはありませんでした)

編集、Jefromiから:

さくらんぼ狩りは必要なかったかもしれません。リベース前のブランチを単純に再作成することもできます。

git branch FeatureB-old efd3fed
git branch FeatureC-old 893eb78

または、FeatureBとFeatureCのリベースされた位置を破棄したい場合は、以前の場所に戻ります。

git branch -f FeatureB efd3fed
git branch -f FeatureC 893eb78

最後に、必要に応じて、reflogsで提供されている他の表記法を使用できることに注意してください。たとえば、のFeatureC@{2}代わりに使用できます893eb78。これは「FeatureCの2番目の前の位置」を意味します。ただし、これはreflogを表示した直後にのみ使用するように注意してください。ブランチを再度更新すると(移動してコミットすると...)、FeatureC@{2}代わりに17dafb3が参照されるためです。

@Jefromiが私の質問にコメントしたように:

おそらく、masterまたはfeatureC(たとえばfeaturesABCと呼ばれる)から新しいブランチを作成し、それぞれをマージして、機能ブランチをそのままにしておく必要があります。さまざまな機能ブランチの独立した履歴を保持するのは良いことです。

*正確には、古いコミットオブジェクトは単にリポジトリに残されます。古いぶら下がっているコミットでいっぱいのレポを望まないので、それらは最終的には剪定されます。これは最初git gcに実行され、コミットが少なくとも2週間前に発生します(によって構成されますgc.pruneExpire)。

于 2010-04-23T06:37:00.943 に答える
1

他のすべてが失敗した場合は、マスターから再起動しgit cherry-pick、BまたはCのすべてのコミットを実行してそれらのブランチを再作成できます。これが唯一の解決策である場合、他の誰かがすでにスクリプトを書いていることを願っています...

于 2010-04-22T13:08:45.573 に答える
1

git rebase --onto <old-merge-base from B> A CC から A までのすべてをマスター上のポイントにリベースするために使用できます。それはあなたに残します:

master    x-x-x-x-x-x-x-x-x-x
             \       \
FeatureA      1-2-3   \
                       \
FeatureB                A'-B'
                            \ 
FeatureC                     X'-Y'-Z'-W

リベースしたいポイントを見つけるには、git の reflog とgit merge-base– の組み合わせを使用できますが、A のマージ ベースにリベースして、次のような履歴を持つこともできます。

master    x-x-x-x-x-x-x-x-x-x
            |\ 
FeatureA    | 1-2-3
             \
FeatureB       A'-B'
                    \ 
FeatureC             X'-Y'-Z'-W

( git rebase --onto $(git merge-base A master) A C)

于 2010-04-23T10:06:30.090 に答える