web-dev-qa-db-ja.com

マージマスターを機能ブランチにGit

Gitには次のような状況があるとしましょう。

  1. 作成されたリポジトリ

    mkdir GitTest2
    cd GitTest2
    git init
    
  2. マスターでいくつかの変更が行われ、コミットされます。

    echo "On Master" > file
    git commit -a -m "Initial commit"
    
  3. Feature1はマスターから分岐し、いくつかの作業が行われます。

    git branch feature1
    git checkout feature1
    echo "Feature1" > featureFile
    git commit -a -m "Commit for feature1"
    
  4. その間、マスターコードにバグが発見され、hotfix-branchが確立されます。

    git checkout master
    git branch hotfix1
    git checkout hotfix1
    
  5. このバグは修正プログラムブランチで修正され、(おそらくプルリクエスト/コードレビューの後で)マスターにマージされました。

    echo "Bugfix" > bugfixFile
    git commit -a -m "Bugfix Commit"
    git checkout master
    git merge --no-ff hotfix1
    
  6. Feature1の開発は続きます。

    git checkout feature1
    

今私の質問:私は私の機能ブランチに修正プログラムが必要だとします。コミットを機能ブランチに重複させずにこれを達成するにはどうすればよいですか?機能の実装とは無関係に、機能ブランチで2つの新しいコミットが発生しないようにしたいです。プルリクエストを使用する場合、これは特に重要です。これらのコミットはすべてプルリクエストにも含まれています。これは既に行われていますが、修正する必要があります(修正プログラムは既にマスターに含まれているため)。

私はgit merge master --ff-onlyを実行することはできません: "致命的:早送りすることは不可能です、中止します。"しかし、これが私を助けたかどうか私はわかりません。

776
theomega

あなたはmasterにあなたのブランチをリベースすることができるはずです:

git checkout feature1
git rebase master

発生するすべての競合を管理します。バグ修正(既にマスターになっている)でコミットすると、gitは変更がないこと、そしておそらくそれらが既に適用されていることを言います。その後、(すでにマスターにあるコミットをスキップしながら)リベースを続行します。

git rebase --skip

あなたの機能ブランチでgit logを実行すると、バグ修正コミットは一度だけ、そしてマスター部分に現れるのがわかります。

より詳細な議論のために、この正確なユースケースをカバーするgit rebasehttps://git-scm.com/docs/git-rebase )上のGit本のドキュメントを見てください。

================追加のコンテキストの編集====================

この回答は、@ theomegaが尋ねた質問に対して、彼の特定の状況を考慮に入れて提供されました。この部分に注意してください。

機能の実装に関係のない自分の機能ブランチへの[...]のコミットを防ぎたい。

彼のプライベートブランチをmasterに使うのは、まさにその結果をもたらすものです。対照的に、masterを彼のブランチにマージすることは彼が具体的には起こりたくないを正確に行うでしょう。 。

質問のタイトルを読むユーザーに対処するには、質問の実際の内容とコンテキストを読み飛ばし、それから彼らの(異なる)ユースケースに当てはまると仮定してトップの答えだけを盲目的に読んでください。

  • プライベートブランチのみをリベースします(つまり、ローカルリポジトリにのみ存在し、他のユーザーと共有されていない)。共有ブランチをリベースすると、他の人が持っているかもしれないコピーが「壊れ」ます。
  • ブランチからの変更(それがマスターブランチであろうと別のブランチであろうと)をパブリックブランチに統合したい場合(例えば、プルリクエストを開くためにブランチをプッシュしたが、マスターとの衝突があるため、更新する必要があります)これらの衝突を解決するためのブランチ)それらをマージする必要があります(例えば@ Svenの答えのようにgit merge masterで)。
  • それがあなたの好みならばブランチをあなたのローカルのプライベートブランチにマージすることもできますが、それはあなたのブランチで "外国の"コミットをもたらすことになることに注意してください。

最後に、@ theomegaに対するものであってもこの回答があなたの状況に最適ではないという事実に不満を抱いているのであれば、以下のコメントを追加することは特に役に立ちません。 @theomegaだけがします。

464
David Sulc

マスターブランチを機能ブランチにマージする方法簡単です。

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初心者のためのものを台無しにするでしょう。

908
Sven

この記事に基づいて あなたがする必要があります:

  • masterの新しいバージョンに基づいている新しいブランチを作成します
  • 古い機能ブランチを新しい機能ブランチにマージする
  • 新機能ブランチで競合を解決

このようにあなたの歴史はあなたが後方併合を必要としないので明確にとどまります。そして、あなたはgit rebaseを必要としないので、あなたはそんなに慎重になる必要はありません

59
zimi

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)新しいブランチで、あなたの機能とマスターブランチの間の衝突を解決します。

完了しました。今すぐあなたの機能を開発し続けるために新しいブランチを使ってください。

22
jkdev

あなたが必要としている 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にマージしたことを認識します。もう一度、それを「スキップ」してください。

9
Bob Gilmore

これはあなたの現在のブランチにあなたのマスターブランチをマージするのに使用できるスクリプトです。

スクリプトは次のことを行います。

  • マスターブランチに切り替えます
  • マスターブランチを引っ張る
  • 現在のブランチに戻る
  • マスターブランチを現在のブランチにマージします

このコードをバッチファイル(.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
6
Aaron M.