web-dev-qa-db-ja.com

リベースされたブランチからブランチをリベースする方法は?

だから私の歴史は次のようになります:

o---o---o---o master \ o---o---o A \ o B

だから、説明する:

  • Aから始まったブランチmasterがあります
  • Bから開始したブランチA(1つのコミットのみ)があります

私が欲しいのはこれです:

o---o---o---o master \ o---o---o A \ o B


私がしたことは:

1)。

git checkout A git rebase master

これにより多くの競合が発生し、修正にかなりの時間を費やした後、次の履歴が浮上しました。

o---o---o---o master \ o---o---o A

まさに私が欲しかったものです。

Bが今どこにあるのかわかりません)


2)。

この後、私はたくさんの押しつぶしを行い、Aのコミットの順序を変更して、履歴を希望どおりに見せました。


3)。

さて、私もやりたいことは:

git checkout B git rebase A

しかし、これは機能していないようで、理由はわかりません。 git logを実行すると、手順1を実行する前にあったコミットが表示されます。

また、ステップ1ですでに解決したのと同じ膨大な数の競合が発生します。私はそれを実行するのにかなりの時間を費やしました。もう一度実行したくありません。

この例--ontoの使用を提案しました。

git checkout B git rebase --onto A

しかし、これによりBのコミットが完全に削除され、ABが同じコミット、つまりAの最後のコミットを指すようになります。


私の質問は:BがAから始まったように見えるように、AからBを効果的にリベースするにはどうすればよいですか? (これは実際には最初は真実でした)。

私の推測では、--ontoを間違って使用しています。または、他の何かを使用する必要があること(cherry-pickなど)。

43
Radu Murzea

短い回答BがAから始まったように見えるように、AからBを効果的にリベースするにはどうすればよいですか? 移動したい場合1つだけcommit:

git rebase --onto A B~ B

移動したい場合は1つコミットを使用します。

git rebase --onto A old_A B

答えの残り。

Bのブランチはまだ存在しています(チェックアウトできます)が、その親はAが以前にあった正確なコミットオブジェクトです。
これをグラフィカルに表示するには、以下を使用します。

git log --graph --decorate --all

すべてのブランチと、それらが互いに対してどこにあるかを確認します。

最初に持っていたもの:

o---o---o---o  master
     \
      o---o---o  A
               \
                o B

あなたが今持っているもの:

o---o---o-----------o  master
     \               \
      o---o---o(B~)   o---o---o A
               \
                o B

--ontoを使用するには、開始点と終了点が必要です。使用する:

git rebase --onto [target] [rebasing stops] [rebasing head]
git rebase --onto A B~ B

そしてあなたが得るもの:

o---o---o----------o  master
     \              \
      o---o---o      o---o---o A
            (old_A)           \
                               o B

[branch_name]~は、ブランチの親コミットを示します。

B~は、変更したくないブランチです。 (たまたま古いA

または、BがAを親として持つ唯一のコミットである場合(つまり、Bはマスターから分岐するコミットのチェーンの終わりです)

git checkout B
git rebase master
git checkout B~   # this is the commit before B (the A commit)
git branch -d A   # remove the old A branch (it was rebased, and so is now invalid
git branch A      # recreate the A branch on the commit that is based on the original A
47
Thomas F

私のgitフローにも同じ問題があり、それを行うための最善かつ迅速な方法を見つけました。

(1)最初のプロジェクト履歴:

    master ---A---B---C
                \
                 D---E---F feature1
                          \
                           G---H feature2

(2)feature1をマスターにリベースし、強制的にプッシュします。

    master ---A---B------------------------C
                \                           \
                 D---E---F feature1(old)     D---E---F feature1
                          \
                           G---H feature2

(3)feature2をfeatrue1(新しいもの)にリベースします

    master ---A---B------------------------C
                                            \
                                             D---E---F feature1
                                                      \
                                                       G---H feature2

最も混乱している部分は、どのように行うかです(3)..しかし、誰もそれを行う明確な答えはありません。

多くの人が私と同じ問題に遭遇したと思います。「rebase --onto」を実行しようとしたときに、feature1(old)が見つかりました実際には存在しません!

    git rebase --onto feature1 feature1(old) feature2

解決策は、代わりに以下を使用することです:

    git rebase --onto feature1 feature1@{1} feature2

構文feature1 @ {1}は「リベース前のfeature1の最後の既知の状態」を意味し、回答は から参照されます-ギット

14
Timmy Lin

すでにAをリベースしている場合。Bがそのままになっているはずです。 Aであったブランチ(ポインタ)は、新しい場所に移動しただけです。

あなたが提案したように、BをAに効果的にリベースするために私が推奨するのは、「チェリーピック」を使用することです。このコマンドは、コミットで行われた変更を、それを実行するブランチに適用しようとします。

したがって、Bが最初にポイントしたコミットのコミットIDが「123456」である場合、現在の「B」をgit branch -f B Aを使用して新しい「A」と同じ場所に移動し、git cherry-pick 123456を実行することをお勧めします変更をAに適用します。

--ontoフラグは、コミットを適用するターゲットの場所を設定するために使用されていると思います。デフォルトは "upstream"です(ソース: http://git-scm.com/docs/git- rebase )。

Rebaseコマンドの考え方は次のとおりです。

git rebase --onto <Starting here> <Apply all commits from HERE> <TO HERE>

これを使用すると、Bをマスターにリベースしてから、AをBの前のコミットにポイントする方がおそらく簡単でした。

git rebase master B

(開始点(--onto)は暗黙的に「マスター」であるため)

次に、git branch -f A B^を使用します(^は「の親」を意味します)

2
Tom Rees