Gitブランチをマスターにマージする最良の(そして最も安全な)方法は何ですか?


2104

から新しいブランチmasterが作成され、それをと呼びますtest

master他のブランチにコミットするか作成して、後でにマージする開発者が何人かいますmaster

たとえば、作業にtest数日かかっており、test内部のコミットで継続的に更新したいとしますmaster

私はするだろうgit pull origin masterからtest

質問1:これは正しいアプローチですか?他の開発者も、私が作業していたのと同じファイルで簡単に作業できたでしょう。


これで私の作業testは完了し、それをにマージする準備ができましたmaster。ここに私が考えることができる2つの方法があります:

A:

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test 

B:

git checkout test
git pull origin master
git checkout master
git merge test

--rebase私の理解から、リベースは変更を取得し、そのmaster上に鉱山をスタックするため、他の人が行った変更を上書きする可能性があるため、私は使用していません。

質問2:これら2つの方法のどちらが正しいですか?そこでの違いは何ですか?

これらすべての目標は、testブランチで起こっていることを最新の状態に保つことでmasterあり、後でそれらをマージしてmaster、タイムラインをできるだけ線形に保つことを期待できます。


18
いいえ。リベースは上書きせず、より明確な履歴を取得しようとするだけです。マスターの後半に履歴を再アタッチ(または偽造)して
Junchen Liu

7
リベースはコミットを上書きしません。コミットを取り消し、マスターブランチのコミットをテストブランチに適用し、コミットをテストに戻します。
zundi

回答:


2993

これをどうやって

git checkout master
git pull origin master
git merge test
git push origin master

リモートブランチからローカルブランチがある場合、このブランチ以外のブランチをリモートブランチとマージすることに不安を感じます。また、自分がプッシュしたいものに満足するまで、自分の変更をプッシュしません。また、自分と自分のローカルリポジトリのためだけのものはプッシュしません。あなたの説明では、それtestはあなただけのものですか?それを公開する理由はありません。

gitは常にあなたや他の人の変更を尊重しようとします--rebase。私はそれを適切に説明できるとは思わないので、Gitの本を見てください-リベースまたはgit対応:リベースの概要を少し説明してください。それはかなりクールな機能です


2
git merge testくれfatal: 'test' does not point to a commitます。私はgit logテストブランチでコミットポイントを探し、マスターブランチに切り替えてから実行する必要がありますgit merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234
Duncanmoo 2014

17
@Duncanmooええと、もちろんブランチtestが存在している必要があります。もちろん、代わりにcommitハッシュを使用できますが、通常はブランチ名を使用する方が簡単です。内部的にHEADは、ブランチのハッシュを取得するだけです。
KingCrunch 14

44
@shanyangquリモートから最新の変更を取得します。一人で作業する場合は、1つのシステムだけで問題はありません。ただし、別のシステムから(おそらく別の開発者から)プッシュされた変更がある場合、マージをプッシュしようとするとすぐに競合が発生します(4番目のステップ)。現在の唯一の解決策は、ローカルマスターをリモートマスターにマージすることです。これにより、かなり醜い「マージされたマスターからオリジン/マスター」へのマージコミットが行われます。したがって、マージの前にプルを行うことは常に良い考えです
KingCrunch

7
「あなたの説明では、そのテストはあなたのためだけのもののようです。それでそれを公開する理由はありません。たとえば、ローカルドライブの障害に対するバックアップをサーバーが提供している場合や、バックアップを実行する別の手段がない場合は、ローカルブランチをサーバーにプッシュすることをお勧めします。
エリック

5
「...また、私がプッシュしたいものに満足するまで、変更をプッシュしません...」ローカルマシンが停止し、日々の作業に備えて、コードをバックアップするためにプッシュしないでください。なくなった?
リッチストーン

400

これは非常に実用的な質問ですが、上記のすべての答えは実用的ではありません。

お気に入り

git checkout master
git pull origin master
git merge test
git push origin master

このアプローチには2つの問題があります

  1. テストブランチとマスターブランチの間に競合があるかどうかがわからないため、安全ではありません。

  2. すべてのテストコミットをマスターで1つのマージコミットに「絞り込み」ます。つまり、masterブランチでは、testブランチのすべての変更ログを表示できません。

したがって、いくつかの競合があると思われる場合は、次のgit操作を実行できます。

git checkout test
git pull 
git checkout master
git pull
git merge --no-ff --no-commit test

mergecommitにテストし、による早送りコミットを回避する--no-ff

競合が発生した場合、実行git statusして競合の詳細を確認し、解決を試みることができます

git status

対立を解決したら、または対立がなければ、私たちcommitpush彼らは

git commit -m 'merge test branch'
git push

しかし、この方法ではテストブランチにログインした変更履歴が失われ、マスターブランチが他の開発者がプロ​​ジェクトの履歴を理解するのが難しくなります。

したがって、最良の方法は、rebase代わりに使用することですmerge(この時点で、ブランチの競合を解決したと仮定します)。

以下は1つの簡単なサンプルです。高度な操作については、http://git-scm.com/book/en/v2/Git-Branching-Rebasingを参照してください。

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

はい、アッパーを完了すると、TestブランチのすべてのコミットがMasterブランチのヘッドに移動されます。リベースの主な利点は、直線的でよりクリーンなプロジェクト履歴が得られることです。

避ける必要があるのはrebase、マスターブランチなどのパブリックブランチでは絶対に使用しないことです。

次のような操作は行わないでください

git checkout master
git rebase -i test

https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasingの詳細

付録:

  • リベース操作について不明な点がある場合は、https://git-scm.com/book/en/v2/Git-Branching-Rebasingを参照してください。

4
後でmasterにマージするために、テストブランチをリベースする方法に同意します。他の回答でも正解です。これにより、バージョン管理システムの目的である「ライナーと非常にクリーンなプロジェクトが得られる」と著者が述べているように、ブランチテストの変更履歴をマスターのヘッドに保持します。
le0diaz 2016

16
「テストブランチとマスターブランチの間に競合があるかどうかわからないため、安全な方法ではありません」という記述は当てはまりません。マージはいつでも中止できます。また、競合がない場合でも、最後のローカルコミットがプッシュされない限り、いつでも元に戻すことができます。gitを正しく理解しないと、いくつかのことは少し恐ろしいか不明瞭に見えるかもしれませんが、「安全でない」はまったく間違っています。他の人と間違った情報を混同しないように注意してください。
Paul van Leeuwen

4
@PaulvanLeeuwenに同意します。テストブランチをマスターにgitマージすると、競合が通知され、変更をステップインしてマージする場所が通知されます。完了したら、マージをコミットしてプッシュバックします。後悔したり、正しくマージできないと思われる場合は、いつでも作業を破棄してマスターからプルすることができます。ですから、それは間違いなく危険ではありません..
Juan

3
なぜ-iをリベースするのですか?
MushyPeas 2017年

8
リベースは本質的にマージより安全ではありません。マージのより安全なオプションとしてリベースを提案するのは間違っています。リベースは有効な戦略ですが、ユーザーが注意する必要があるより多くの警告が付属しています。
Ikke 2018年

90

リベースもマージも誰かの変更を上書きしてはなりません(競合を解決するときにそうすることを選択した場合を除く)。

開発中の通常のアプローチは

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

マスターにマージする準備ができたら、

git checkout master
git log ..test # if you're curious
git merge test
git push

マージで何かを壊すことを心配しているなら、あなたのgit merge --abortためにあります。

マージの手段としてプッシュとプルを使用するのはばかげています。また、なぜテストを元に戻すのかわかりません。


1
このプロセスはコミットの数を増やします。ブランチを切り替えるたびに、ブランチをコミットする必要があります。
iBug 14

2
何?ブランチを切り替えるたびにコミット数が増えると言っていますか?それとも、ブランチを切り替えるたびに「ブランチをコミットする」必要があると言っていますか?1つ目は真実ではなく、2つ目が何を意味するのかわかりません。
raylu 14

チェックアウトの前に、ブランチをコミットする必要があります。それは私が言っているものです
iBug

11
あなたはしません:それは(物事の一つ)のgit stashためです。
msanford 2014

1
または、(ローカルブランチの)最後のコミットを修正して、プッシュする前にそれを完璧なものにすることもできます。
whihathac

42

最初に、マージされるブランチを可能な限りクリーンにします。テストを実行し、状態が希望どおりであることを確認します。git squashで新しいコミットをクリーンアップします。

ほかKingCrunches答え、私が使用することをお勧め

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

他のブランチで多くのコミットを行った可能性がありますが、マスターブランチでは1つのコミットのみにする必要があります。コミット履歴をできる限りクリーンに保つには、テストブランチからのすべてのコミットをマスターブランチの1つのコミットに押しつぶしたい場合があります(Git:押しつぶすか押しつぶさないか?も参照)。次に、コミットメッセージを非常に表現力豊かなものに書き換えることもできます。コードを掘り下げることなく、読みやすく理解しやすいもの。

編集:あなたは興味があるかもしれません

したがって、GitHubでは、機能ブランチに対して次のようにしますmybranch

オリジンから最新のものを入手する

$ git checkout master
$ git pull origin master

マージベースハッシュを見つけます。

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

最初のものだけがであることを確認しpickてください。残りはs

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

次に、非常に適切なコミットメッセージを選択し、GitHubにプッシュします。次にプルリクエストを行います。

プルリクエストのマージ後、ローカルで削除できます:

$ git branch -d mybranch

そしてGitHubで

$ git push origin :mybranch

マスターブランチでは1つのコミットのみである必要があります」、必ずしもそうとは限りません。歴史を残したいと思うかもしれません
ココワラ

承知しました。しかし、単にコミットを押しつぶさないでください
Martin Thoma

--first-parentが最善の解決策のようだと思います。davidchudzicki.com/posts/first-parent
bkribbs

7

古いスレッドですが、自分のやり方がわかりません。これは、リベースで作業し、マスターの(機能)ブランチからのすべてのコミットをマージしたい人にとっては価値があるかもしれません。途中で競合がある場合は、コミットごとに解決できます。プロセス中は完全に制御でき、いつでも中止できます。

マスターとブランチを最新の状態にする:

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

マスターの上にブランチをマージ:

git checkout <branch_name>
git rebase master

オプション:リベース中に競合が発生した場合:

まず、ファイルの競合を解決します。次に:

git add .
git rebase --continue

リベースしたブランチをプッシュします。

git push origin <branch_name>

今、あなたは2つのオプションを持っています:

  • A)PRを作成し(たとえば、GitHubで)、UIを介してそこにマージします。
  • B)コマンドラインに戻り、ブランチをマスターにマージします
git checkout master
git merge --no-ff <branch_name>
git push origin master

できました。


6

これは、チームでの仕事で使用するワークフローです。シナリオはあなたが説明したとおりです。最初に、私がブランチでtest作業している間にマスターに追加されたものをプルインするためにマスターでリベースし、作業を終えたらtest

git pull -r upstream master

これにより、testブランチをフォークして変更をマスターに適用した後、マスターの現在の状態を「上に」テストするために加えた変更をマスターに適用します。テストで編集したのと同じファイルに他の人が変更を加えた場合、ここで競合が発生する可能性があります。もしあれば、手動で修正してコミットする必要があります。それが完了したら、masterブランチに切り替えてtest問題なくマージすることをお勧めします。


3
git checkout master
git pull origin master
# Merge branch test into master
git merge test

マージ後、ファイルが変更された場合、マージすると「競合の解決」のエラーが発生します

したがって、最初にすべての競合を解決する必要があります。次に、すべての変更を再度コミットしてからプッシュする必要があります

git push origin master

これは、テストブランチで誰が変更を行ったかを知っているためです。


3

リベースの方法を使用します。それは主に、意味的にあなたのケースを完全に反映しているからです。あなたがしたいことは、現在のブランチの状態をリフレッシュして、最新のものに基づいているかのように「ふり」をすることです。

だから、チェックアウトすらせずにmaster、私は:

git fetch origin
git rebase -i origin/master
# ...solve possible conflicts here

もちろん、オリジンからフェッチするだけではローカルの状態は更新masterされません(マージを実行しないため)が、私たちの目的にはまったく問題はありません。時間を節約するために、切り替えを回避したいと考えています。


2

@KingCrunchの答えは多くの場合うまくいくはずです。発生する可能性のある1つの問題は、テストから最新のものを取得する必要がある別のマシン上にいる可能性があることです。だから、私は最初にプルテストをお勧めします。リビジョンは次のようになります。

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master

0

プルはマスターにマージすることを意味するため、プルするにはブランチをチェックアウトする必要があり、マージするにはワークツリーが必要です。

git checkout master
git pull

最初にチェックアウトする必要はありません。リベースは2つの引数で正しいことを行います

git rebase master test  

git checkout master
git merge test

git pushはデフォルトで、こことリモートに存在するすべてのブランチをプッシュします

git push
git checkout test

0

タイトルが「最善の方法」と言っているように、忍耐力のマージ戦略を検討することは良い考えだと思います 。

送信元:https : //git-scm.com/docs/merge-strategies

このオプションを使用すると、 'merge-recursive'は、余計な一致行(たとえば、個別の関数のブレース)が原因で発生することがある誤マージを回避するために、少し余分な時間を費やします。マージするブランチが大幅に分岐した場合に使用します。git-diff [1] --patienceも参照してください。

使用法:

git fetch
git merge -s recursive -X patience origin/master

Gitエイリアス

私は常にこれにエイリアスを使用しています。たとえば、一度実行します。

 git config --global alias.pmerge 'merge -s recursive -X patience'

今あなたはできる:

git fetch
git pmerge origin/master

0

これはGitLabからです:ただ指示に従ってください:

ここに画像の説明を入力してください


0

私は開発および機能ブランチごとに答えます

機能ブランチを使用していて、以下のコマンドを使用して更新する必要がある場合:git checkout develop git pull git checkout feature / xyz git merge develop

これで、機能が開発で更新され、変更をプッシュできます。

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