web-dev-qa-db-ja.com

Git:特定のコミットにリベースする方法は?

他のブランチのHEADではなく、特定のコミットにリベースしたい:

A --- B --- C          master
 \
  \-- D                topic

A --- B --- C          master
       \
        \-- D          topic

の代わりに

A --- B --- C          master
             \
              \-- D    topic

どうすればそれを達成できますか?

126
Ondra Žižka

好きなコミットで一時ブランチを作成し、その単純な形式でリベースを使用することで、--ontoパラメーターの使用を回避できます。

git branch temp master^
git checkout topic
git rebase temp
git branch -d temp
78
Adam Dymitruk

直接的なアプローチをとることもできます:

git checkout topic
git rebase <commitB>
59
r0hitsharma

「onto」オプションを使用します。

git rebase --onto master^ D^ D
45
Adam Dymitruk

上記のjszによるコメントは私に多大な苦痛を与えなかったので、他のコミットの上にコミットをリベース/移動するために使用してきた、それに基づいたステップバイステップのレシピがあります:

  1. リベース(移動)するブランチの以前のブランチポイントを見つけます-古い親と呼びます。上記の例ではA
  2. ブランチを移動する先のコミットを見つけます-新しい親と呼びます。例ではB
  3. ブランチ(移動するブランチ)にいる必要があります。
  4. リベースを適用します:git rebase --onto <new parent> <old parent>

上記の例では、次のように簡単です。

   git checkout topic
   git rebase --onto B A
11
Nestor Milyaev

トピックソリューション

投稿された質問に答えるための正しいコマンドは、次のいずれかです(ブランチtopicがすでにチェックアウトされていると仮定):

git rebase --onto B master
git rebase --onto master~1 master
git rebase --onto B A
git rebase --onto B C
git rebase --onto B

topicがチェックアウトされていない場合、次のようにtopicをコマンドに追加します(最後のコマンドを除く)。

git rebase --onto B master topic

または、最初にブランチをチェックアウトします:

git checkout topic

コミットの文字列をターゲットコミットにリベースする

ドキュメントに記載されている必要なコマンドの基本形式は次のとおりです。

git rebase --onto <Target> [<Upstream> [<Branch>]]

<Branch>はオプションであり、コマンドの残りを実行する前に指定されたブランチをチェックアウトするだけです。リベースするブランチを既にチェックアウトしている場合、これは必要ありません。 <Upstream>を指定するには<Branch>を指定する必要があります。指定しないと、gitは<Upstream>を指定していると見なします。

<Target>は、コミットの文字列を添付するコミットです。ブランチ名を指定する場合、そのブランチのヘッドコミットを指定するだけです。 <Target>は、移動するコミットの文字列に含まれないコミットです。例えば:

A --- B --- C --- D         master
      \
       \-- X --- Y --- Z    feature

機能ブランチ全体を移動するには、<Target>としてXYZ、またはfeatureを選択することはできません。これらはすべてグループ内でコミットされるためです。移動されています。

<Upstream>は、2つの異なることを意味する可能性があるため、特別です。チェックアウトされたブランチの祖先であるコミットである場合、カットポイントとして機能します。私が提供した例では、これはCD、またはmasterではないものになります。 <Upstream>の後、チェックアウトされたブランチの先頭までのすべてのコミットが移動されます。

ただし、<Upstream>が祖先でない場合、gitは、チェックアウトされたブランチを持つ共通の祖先が見つかるまで、指定されたコミットからチェーンをバックアップします(見つからない場合は中止します)。この場合、<Upstream> of BCD、またはmasterのすべてがコミットBになり、カットポイントとして機能します。 <Upstream>はそれ自体がオプションのコマンドであり、指定されていない場合、gitはmasterを入力するのと同等のチェックアウトされたブランチの親を調べます。

Gitは、カットして移動するコミットを選択したので、<Target>に適用し、ターゲットに既に適用されているコミットをスキップします。

興味深い例と結果

この出発点の使用:

A --- B --- C --- D --- E         master
            \
             \-- X --- Y --- Z    feature
  • git rebase --onto D A feature
    コミットBCXYZを適用して、Dをコミットし、最後にスキップしますBおよびCは、既に適用されているためです。

  • git rebase --onto C X feature
    コミットYおよびZをコミットCに適用し、コミットを効果的に削除しますX

3
Isaac Brown

上記のソリューションの混合物を使用しました。

$ git branch temp <specific sha1>
$ git rebase --onto temp master topic
$ git branch -d temp

読みやすく、理解しやすいことがわかりました。受け入れられた解決策により、マージの競合が発生しました(手作業で修正するのが面倒です)。

$ git rebase temp
First, rewinding head to replay your work on top of it...
Applying: <git comment>
Using index info to reconstruct a base tree...
M       pom.xml
.git/rebase-apply/patch:10: trailing whitespace.
    <some code>
.git/rebase-apply/patch:17: trailing whitespace.
        <some other code>
warning: 2 lines add whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging pom.xml
CONFLICT (content): Merge conflict in pom.xml
error: Failed to merge in the changes.
Patch failed at 0001 <git comment>
The copy of the patch that failed is found in: .git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
2
malat

リベースは非常に基本的なため、ここでは Nestor Milyaevの答え の拡張版を示します。 jsz'sSimon South's からのコメントを組み合わせる Adam Dymitruk's answer は、このコマンドを生成します。このコマンドはtopicブランチで機能します。 masterブランチのコミットAまたはC

git checkout topic
git rebase --onto <commit-B> <pre-rebase-A-or-post-rebase-C-or-base-branch-name>

最後の引数が必要であることに注意してください(そうでない場合、Bをコミットするためにブランチを巻き戻します)。

例:

# if topic branches from master commit A:
git checkout topic
git rebase --onto <commit-B> <commit-A>
# if topic branches from master commit C:
git checkout topic
git rebase --onto <commit-B> <commit-C>
# regardless of whether topic branches from master commit A or C:
git checkout topic
git rebase --onto <commit-B> master

したがって、最後のコマンドは、私が通常使用するものです。

1
Zack Morris

それを行う別の方法、または複数のコミットに戻る場合があります。

nのコミット数に戻る例を次に示します。

git branch topic master~n

この質問のために、これも行うことができます:

git branch topic master~1

このコマンドはgit version 2.7.4で完全に機能します。他のバージョンではテストしていません。

0
Talha Ashraf