他のブランチのHEADではなく、特定のコミットにリベースしたい:
A --- B --- C master
\
\-- D topic
に
A --- B --- C master
\
\-- D topic
の代わりに
A --- B --- C master
\
\-- D topic
どうすればそれを達成できますか?
好きなコミットで一時ブランチを作成し、その単純な形式でリベースを使用することで、--ontoパラメーターの使用を回避できます。
git branch temp master^
git checkout topic
git rebase temp
git branch -d temp
直接的なアプローチをとることもできます:
git checkout topic
git rebase <commitB>
「onto」オプションを使用します。
git rebase --onto master^ D^ D
上記のjszによるコメントは私に多大な苦痛を与えなかったので、他のコミットの上にコミットをリベース/移動するために使用してきた、それに基づいたステップバイステップのレシピがあります:
git rebase --onto <new parent> <old parent>
上記の例では、次のように簡単です。
git checkout topic
git rebase --onto B A
投稿された質問に答えるための正しいコマンドは、次のいずれかです(ブランチ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>
としてX
、Y
、Z
、またはfeature
を選択することはできません。これらはすべてグループ内でコミットされるためです。移動されています。
<Upstream>
は、2つの異なることを意味する可能性があるため、特別です。チェックアウトされたブランチの祖先であるコミットである場合、カットポイントとして機能します。私が提供した例では、これはC
、D
、またはmaster
ではないものになります。 <Upstream>
の後、チェックアウトされたブランチの先頭までのすべてのコミットが移動されます。
ただし、<Upstream>
が祖先でない場合、gitは、チェックアウトされたブランチを持つ共通の祖先が見つかるまで、指定されたコミットからチェーンをバックアップします(見つからない場合は中止します)。この場合、<Upstream>
of B
、C
、D
、またはmaster
のすべてがコミットB
になり、カットポイントとして機能します。 <Upstream>
はそれ自体がオプションのコマンドであり、指定されていない場合、gitはmaster
を入力するのと同等のチェックアウトされたブランチの親を調べます。
Gitは、カットして移動するコミットを選択したので、<Target>
に適用し、ターゲットに既に適用されているコミットをスキップします。
この出発点の使用:
A --- B --- C --- D --- E master
\
\-- X --- Y --- Z feature
git rebase --onto D A feature
コミットB
、C
、X
、Y
、Z
を適用して、D
をコミットし、最後にスキップしますB
およびC
は、既に適用されているためです。
git rebase --onto C X feature
コミットY
およびZ
をコミットC
に適用し、コミットを効果的に削除しますX
上記のソリューションの混合物を使用しました。
$ 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".
リベースは非常に基本的なため、ここでは Nestor Milyaevの答え の拡張版を示します。 jsz's と Simon 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
したがって、最後のコマンドは、私が通常使用するものです。
それを行う別の方法、または複数のコミットに戻る場合があります。
n
のコミット数に戻る例を次に示します。
git branch topic master~n
この質問のために、これも行うことができます:
git branch topic master~1
このコマンドはgit version 2.7.4
で完全に機能します。他のバージョンではテストしていません。