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


1017

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. 一方、マスターコードにバグが発見され、ホットフィックスブランチが確立されます。

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

    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「致命的:早送りして中止することはできません。」ということはできませんが、これが役に立ったかどうかはわかりません。


8
ブランチfeature1が完全にローカルである場合は、をご覧くださいgit rebase
ジョークスター2013

19
ありがとう、gitの初心者にとって、git rebase私には黒魔術のように思えます...
theomega

13
ブランチが機能である場合-このブランチの目的は新しい機能を表示することであるため、そこではバグ修正のみが発生しないようにする必要があります(少なくともブロッキングバグでない場合)。このバグは、修正を伴うコミットが存在するマスターとマージされると修正されます。
gipi 2013年

21
おそらく3. git branch feature1と4.にgit checkout feature1組み合わせることができる初心者には注目に値するでしょうgit checkout -b feature1。完全に減らすことができますgit checkout -b hotfix1 master
Naruto Sempai

3
現在受け入れられている回答はひどいので、戻って受け入れられた回答を変更してもかまいません。
2017

回答:


1218

マスターブランチを機能ブランチにマージするにはどうすればよいですか?簡単:

git checkout feature1
git merge master

ここでは早送りマージを強制することはできません。機能ブランチとマスターブランチの両方にコミットしました。現在、早送りは不可能です。

見ていGitFlowを。これは、従うことができるgitの分岐モデルであり、あなたはすでに無意識のうちにそうしていました。これはGitの拡張機能でもあり、手動で行う必要のある、自動的に処理を実行する新しいワークフローステップにいくつかのコマンドを追加します。

では、ワークフローで何をしましたか?処理するブランチが2つあり、feature1ブランチは基本的にGitFlowモデルの「開発」ブランチです。

マスターからホットフィックスブランチを作成し、マージして戻しました。そして今、あなたは行き​​詰まっています。

GitFlowモデルでは、修正プログラムを開発ブランチにもマージするように求められます。開発ブランチは、「feature1」です。

したがって、本当の答えは次のとおりです。

git checkout feature1
git merge --no-ff hotfix1

これにより、修正プログラム内で行われたすべての変更が機能ブランチに追加されますが、それらの変更のみが追加されます。それらはブランチの他の開発変更と競合する可能性がありますが、最終的に機能ブランチをマージしてマスターに戻してもマスターブランチと競合することはありません。

リベースには十分注意してください。リポジトリのローカルに残った変更が他のリポジトリにプッシュされなかった場合などにのみ、リベースします。リベースは、ローカルコミットを有用な順序に整理してから世界に投入するための優れたツールですが、後でリベースすると、あなたのようなgit初心者にとって混乱を招きます。


7
いいえ。バグを修正するコミットは、masterブランチとdevelブランチにマージされるとブランチ名が削除されますが、ホットフィックスブランチに一度だけ表示されます。マージコミットは、マージによって導入された変更のみを表示します。これは、重複したコミットのように見えます。しかし、これがgitのしくみです。ブランチしてマージします。実際の開発作業は非マージコミットでのみ行われ、結果が機能するソフトウェアである場合にのみマージが受け入れられます。
スヴェン

42
これは受け入れられる答えになるはずです。これは、GitHubのプルリクエスト機能でもうまく機能します。
Nostalg.io 2015

125
マスターのローカルコピーgit merge masterからがマージされることは注目に値すると思います。誰かが別のブランチをマスターにマージした後に機能ブランチでを実行した場合でも、、、そして、そしてもう一度。git pullgit checkout mastergit pullgit checkout feature1git merge master
ダミック

50
@damickまたはjust git fetchandgit merge origin/master
Yngvar Kristiansen

20
@damick @ yngvar-kristiansen git pull origin masterが自動的orgin/masterに現在のブランチにマージされます
L422Y

613

ブランチをマスターにリベースできるはずです:

git checkout feature1
git rebase master

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

git rebase --skip

あなたが実行した場合git log、あなたの機能ブランチに、あなたはバグ修正がコミット参照してくださいよ、一度だけ、及びマスター部分に表示されます。

詳細な説明については、この正確なユースケースをカバーするgit rebasehttps://git-scm.com/docs/git-rebase)のGitブックのドキュメントを参照してください

================追加コンテキスト用に編集====================

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

機能の実装に関係のない機能ブランチでの[...]コミットを防止したい。

彼のプライベートブランチをmasterでリベースすることがまさにその結果を生むでしょう。対照的に、masterをブランチにマージすると、具体的にはが望まないこと、つまり、ブランチを介して取り組んでいる機能の実装に関連しないコミットが追加されます。

質問のタイトルを読んだユーザーに対処するには、質問の実際のコンテンツとコンテキストをスキップし、それが常に(異なる)ユースケースに当てはまると仮定して、トップアンサーだけを盲目的に読むだけです。詳しく説明します。

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

最後に、@ theomegaの場合でも、この回答が自分の状況に最適ではないという事実に不満がある場合は、以下のコメントを追加しても特に役に立ちません。どの回答を選択するかは制御しません。 @theomegaだけが行います。


136
いいえ、安全ではありません。リベースすると、ブランチの履歴が変更され、ブランチをプルした開発者に影響します。inf act、gitはデフォルトでリベースされたブランチをプッシュすることを許可しません:プッシュ-f時にブランチをリベースされたバージョンで上書きするように強制的に更新する必要があります。注意してください!
David Sulc 2013

17
gitを使用する専門チームはこの問題をどのように処理しますか?ただ注意を払い、慎重に考えてから、-f?それとも、必要なため、完全なワークフローに問題があり-fますか?
theomega 2013

30
ええと、共有されているコードにリベースしない(またはコミット履歴を変更しない)という「神聖な」ルールに挑戦します。これは、ローカルコード専用です。基本的には、変更を「クリーンアップ」するためにリベースしてから共有する必要があります。あなたのケースでは、(別の名前で)新しいリベースのブランチをプッシュし、変更をそのブランチに基づいてベースにするように同僚に依頼することができます(つまり、上記のようにローカルブランチを新しいブランチにリベースすることにより)。次に、feature1Githubから削除します。
David Sulc 2013

19
私がこれまで取り組んできた専門チームのほとんどは、リベースをほとんど使用していません。デフォルトですべてをマージするだけなので、履歴の変更は発生しません。これが私の好みの作業方法です。一方、いくつかのチームが(押した後でしたが。)彼らはそれらをプッシュする前に、「クリーンアップ」のコミットにリベースを使用していない
ジョナサン・ハートリー

11
はい、パブリックブランチをリベースしないでください。しかし、OPの質問は、新しいコミットをmasterプライベートブランチに統合することを扱っているようです(彼は「彼の」ローカルブランチについて言及しています)。その場合、rebase問題はなく、言及した「クリーンアップ」と同じユースケースです。
David Sulc、2015年

69

この記事に基づいて、次のことを行う必要があります。

  • 新しいバージョンのマスターに基づく新しいブランチを作成する

    git branch -b newmaster

  • 古い機能ブランチを新しい機能ブランチにマージします

    git checkout newmaster

  • 新しい機能ブランチでの競合を解決する

最初の2つのコマンドは、と組み合わせることができますgit checkout -b newmaster

これにより、バックマージが不要になるため、履歴が明確になります。また、Gitのリベースを行う必要がないため、それほど注意深くする必要はありません。


7
関連するgitコマンドに各ポイントを追わせるとよいでしょう。そうでなければ、これは確かにより安全でクリーンなオプションであるように私には思えます。
VirgileD 2016年

@zimiリモートブランチがある場合はどうなりますか?新しい更新機能ブランチを再度作成しますか?それとも、リモートアップストリームを設定するだけですか?
BILL

@VirgileD私は、関連するgitコマンドを含む詳細を含む自分の回答を投稿しました。
jkdev 2017年

29

git merge

以下の手順に従うことができます

1. origin/masterブランチをfeatureブランチにマージ

# step1: change branch to master, and pull to update all commits
$ git checkout master
$ git pull

# step2: change branch to target, and pull to update commits
$ git checkout feature
$ git pull

# step3: merge master to feature(⚠️ current is feature branch)
$ git merge master

2. featureブランチをorigin/masterブランチにマージ

origin/masterはリモートマスターブランチmasterですが、ローカルマスターブランチです

$ git checkout master
$ git pull origin/master

$ git merge feature
$ git push origin/master




リベースが宣伝されているように感じます!古き良きマージ:)!
Foreever

27

ジミの答えは、このプロセスを一般的に説明しています。詳細は次のとおりです。

  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. 新しいブランチで、機能とマスターブランチ間の競合を解決します。

できた!新しいブランチを使用して、機能の開発を続けます。


2
この問題は、マスターに対して更新する必要がある場合、開発者が新しいブランチを常に生成する時間を浪費することです。たぶんたくさんのブランチを作っていて、おそらくアクティブな作業中に1日に3回です。すべてのローカルのゴミ箱をクリーンアップする方法と、リモートでそれらを取り除く方法についての説明を書く必要があります。混乱しないように、これらすべてのブランチに名前を付けることについてのアドバイスも必要です。そのビットがなければ、これはブランチシステムを混乱に変えます。
pauljohn32 2017年

4
そうです、これは常に行われるべきではありません。(1)マスターでの変更が機能に必要な場合、または(2)ブランチをマスターとマージしようとしていて、競合が発生する可能性がある場合のみ。また、混乱を避けるために、マージ後にブランチを削除できます。
jkdev 2017年

11

以下は、masterブランチを現在のブランチにマージするために使用できるスクリプトです。

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

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

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

10

「チェリーピック」を実行して、機能ブランチに必要な正確なコミットをプルできる場合があります。

やるgit checkout hotfix1hotfix1ブランチに取得します。次にa git logを実行して、問題のコミットのSHA-1ハッシュ(コミットを一意に識別するランダムな文字と数字の大きなシーケンス)を取得します。それ(または最初の10文字程度)をコピーします。

次に、git checkout feature1機能ブランチに戻ります。

そして、 git cherry-pick <the SHA-1 hash that you just copied>

これにより、そのコミットだけが機能ブランチに取り込まれます。その変更はブランチに反映されます-それを「チェリーピック」するだけです。次に、作業を再開し、編集、コミット、プッシュなどを心の中で行います。

最終的に、あるブランチから機能ブランチに(またはその逆に)別のマージを実行すると、Gitは、その特定のコミットですでにマージされいることを認識し、再度コミットする必要がないことを認識します。「スキップ」してください。


これは良い考えではないと思います。その後、IMO、ホットフィックスコミットは実際には機能ブランチの履歴に表示されますが、基本的には不要です。
Martin Pecka

1
「最終的に、あるブランチから機能ブランチへ(またはその逆)に別のマージを実行すると、gitはすでにマージされていることを認識します[...]」—それが実際に機能する方法ですか?私はgit merge、あなたがほのめかしているように思われるこの「リプレイコミット」の方法では機能しないと思います(「それをスキップするだけ」)。チェリーピッキングとマージを混合すると、明らかに問題が発生する可能性があります。参照:news.ycombinator.com/item?id
ギルデンスターン

0

私は機能ブランチにいて、リファクタリングを行いました。マスター変更を機能ブランチにマージしたいと思います。私はかなり遅れています。機能ブランチにはモジュールが1つの場所から別の場所に移動されているため、マスターの変更をローカルにプルしたくない。プルなしで以下を実行するだけでは機能しません。「すでに最新の状態です」と書かれています。

 //below does not get the latest from remote master to my local feature branch without git pull
    git checkout master 
    git fetch 
    git checkout my-feature-branch 
    git merge master

これは機能しますが、git merge origin / masterを使用することに注意してください:

 git checkout master 
    git fetch 
    git checkout my-feature-branch 
    git merge origin/master
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.