Gitには次のような状況があるとしましょう。
作成されたリポジトリ
mkdir GitTest2
cd GitTest2
git init
マスターでいくつかの変更が行われ、コミットされます。
echo "On Master" > file
git commit -a -m "Initial commit"
Feature1はマスターから分岐し、いくつかの作業が行われます。
git branch feature1
git checkout feature1
echo "Feature1" > featureFile
git commit -a -m "Commit for feature1"
その間、マスターコードにバグが発見され、hotfix-branchが確立されます。
git checkout master
git branch hotfix1
git checkout hotfix1
このバグは修正プログラムブランチで修正され、(おそらくプルリクエスト/コードレビューの後で)マスターにマージされました。
echo "Bugfix" > bugfixFile
git commit -a -m "Bugfix Commit"
git checkout master
git merge --no-ff hotfix1
Feature1の開発は続きます。
git checkout feature1
今私の質問:私は私の機能ブランチに修正プログラムが必要だとします。コミットを機能ブランチに重複させずにこれを達成するにはどうすればよいですか?機能の実装とは無関係に、機能ブランチで2つの新しいコミットが発生しないようにしたいです。プルリクエストを使用する場合、これは特に重要です。これらのコミットはすべてプルリクエストにも含まれています。これは既に行われていますが、修正する必要があります(修正プログラムは既にマスターに含まれているため)。
私はgit merge master --ff-only
を実行することはできません: "致命的:早送りすることは不可能です、中止します。"しかし、これが私を助けたかどうか私はわかりません。
あなたはmasterにあなたのブランチをリベースすることができるはずです:
git checkout feature1
git rebase master
発生するすべての競合を管理します。バグ修正(既にマスターになっている)でコミットすると、gitは変更がないこと、そしておそらくそれらが既に適用されていることを言います。その後、(すでにマスターにあるコミットをスキップしながら)リベースを続行します。
git rebase --skip
あなたの機能ブランチでgit log
を実行すると、バグ修正コミットは一度だけ、そしてマスター部分に現れるのがわかります。
より詳細な議論のために、この正確なユースケースをカバーするgit rebase
( https://git-scm.com/docs/git-rebase )上のGit本のドキュメントを見てください。
================追加のコンテキストの編集====================
この回答は、@ theomegaが尋ねた質問に対して、彼の特定の状況を考慮に入れて提供されました。この部分に注意してください。
機能の実装に関係のない自分の機能ブランチへの[...]のコミットを防ぎたい。
彼のプライベートブランチをmasterに使うのは、まさにその結果をもたらすものです。対照的に、masterを彼のブランチにマージすることは彼が具体的には起こりたくないを正確に行うでしょう。 。
質問のタイトルを読むユーザーに対処するには、質問の実際の内容とコンテキストを読み飛ばし、それから彼らの(異なる)ユースケースに当てはまると仮定してトップの答えだけを盲目的に読んでください。
git merge master
で)。最後に、@ theomegaに対するものであってもこの回答があなたの状況に最適ではないという事実に不満を抱いているのであれば、以下のコメントを追加することは特に役に立ちません。 @theomegaだけがします。
マスターブランチを機能ブランチにマージする方法簡単です。
git checkout feature1
git merge master
ここでは早送りマージを強制しても意味がありません。あなたは両方ともfeatureブランチとmasterブランチにコミットしました。早送りは現在不可能です。
gitflow をご覧ください。それは従うことができるgitのための分岐モデルです、そしてあなたは無意識のうちにすでにしました。これはgitの拡張機能でもあり、これを使用すると手動で実行する必要があることを自動的に実行する新しいワークフローステップ用のコマンドが追加されます。
それで、あなたはあなたのワークフローで何を正しくしましたか? 2つのブランチがあります。あなたのfeature1ブランチは基本的にgitflowモデルの "Develop"ブランチです。
マスターから修正プログラムブランチを作成し、それをマージしました。そして今、あなたは立ち往生しています。
Gitflowモデルは、この修正プログラムをdevelブランチにもマージするように求めています。これはあなたのケースでは "feature1"です。
したがって、本当の答えは次のようになります。
git checkout feature1
git merge --no-ff hotfix1
これにより、修正プログラム内に加えられたすべての変更が機能ブランチに追加されますが、それらの変更のみが含まれます。それらはブランチの他の開発上の変更と衝突するかもしれませんが、最終的にfeatureブランチをmasterにマージしなおしてもmasterブランチと衝突することはありません。
リベースには十分注意してください。行った変更がリポジトリのローカルにある場合にのみ、リベースします。ブランチを他のリポジトリにプッシュしませんでした。リベースはあなたがそれを世界に押し出す前にあなたのローカルコミットを便利な順番に並べるための素晴らしいツールですが、その後リベースすることはあなたのようなgit初心者のためのものを台無しにするでしょう。
この記事に基づいて あなたがする必要があります:
このようにあなたの歴史はあなたが後方併合を必要としないので明確にとどまります。そして、あなたはgit rebaseを必要としないので、あなたはそんなに慎重になる必要はありません
Zimi's answer このプロセスを一般的に説明します。詳細は以下のとおりです。
1)新しいブランチを作成して切り替えます。新しいブランチがmaster
に基づいていることを確認してください。そうすれば、それは最近のホットフィックスを含みます。
git checkout master
git branch feature1_new
git checkout feature1_new
# Or, combined into one command:
git checkout -b feature1_new master
2)新しいブランチに切り替えたら、既存の機能ブランチからの変更をマージします。これにより、修正プログラムのコミットを複製せずにコミットが追加されます。
git merge feature1
3)新しいブランチで、あなたの機能とマスターブランチの間の衝突を解決します。
完了しました。今すぐあなたの機能を開発し続けるために新しいブランチを使ってください。
あなたが必要としている exact commitをあなたの機能ブランチに引き込むために "チェリーピック"をすることができるかもしれません。
Hotfix1ブランチに到達するためにgit checkout hotfix1
を実行してください。次に、問題のコミットのSHA1ハッシュ(コミットを一意に識別するランダムな文字と数字の大きなシーケンス)を取得するためにgit log
を実行します。それ(または最初の10文字程度)をコピーします。
それから、git checkout feature1
を押して、機能ブランチに戻ります。
その後、git cherry-pick <the SHA1 hash that you just copied>
それはそのコミット、そして only そのコミットをあなたの機能ブランチに引き込むでしょう。その変更はブランチにあります - あなたはそれを「チェリーピッキング」しただけです。それから、作業を再開し、編集し、コミットし、プッシュするなどしてあなたの心の内容にします。
結局、あるブランチから自分の機能ブランチに(あるいはその逆に)別のマージを実行するとき、gitはすでに その特定の commitにマージしたことを認識します。もう一度、それを「スキップ」してください。
これはあなたの現在のブランチにあなたのマスターブランチをマージするのに使用できるスクリプトです。
スクリプトは次のことを行います。
このコードをバッチファイル(.bat)として保存し、スクリプトをリポジトリの任意の場所に配置します。それを実行するためにそれをクリックして、あなたは設定されています。
:: This batch file pulls current master and merges into current branch
@echo off
:: Option to use the batch file outside the repo and pass the repo path as an arg
set repoPath=%1
cd %repoPath%
FOR /F "tokens=*" %%g IN ('git rev-parse --abbrev-ref HEAD') do (SET currentBranch=%%g)
echo current branch is %currentBranch%
echo switching to master
git checkout master
echo.
echo pulling Origin master
git pull Origin master
echo.
echo switching back to %currentBranch%
git checkout %currentBranch%
echo.
echo attemting merge master into %currentBranch%
git merge master
echo.
echo script finished successfully
PAUSE