

sampleディレクトリの中のsample.txtというファイルがあったとします。sampleディレクトリに移動してmasterブランチにてsample.txtにhello
masterと書いてaddしてcommitした後に、developブランチを作成しcheckoutします。developブランチではhello
developと書いてaddしてcommitして、masterブランチにチェックアウトしました。masterブランチにdevelopブランチの内容を取り込もうとしてgit
merge developとやって見ればコンフリクトしますよね。

これは、sample.txtというファイルの変更がmasterブランチとdevelopブランチ二つで行われているために、どっちをマージしていいかわからず起こる衝突ですよね。ていうことは、マージの使い所って、developブランチに移動して例えばsampleディレクトリの中にNewsample.txtというファイルを作成して、それをmasterに取り込むって使い方しかできないってことですよね。

仮にdevelopブランチの状態が master + (coomit) + (commit) +
(commit)だったとしてdevelopブランチの変更をmasterブランチにコンフリクトせずにマージを行いたければmasterブランチの状態がmaster
- (developのcoomit) - (developのcommit) - (developのcommit)という状態になければいけない。

developブランチで作業してる間にmasterブランチに変更が加えられてcommitされていた場合、その時点でmasterブランチの状態はmaster
-(developのcoomit) - (developのcommit) -
(developのcommit)ではなく、全く新しいmasterに生まれ変わってるので、masterブランチにいる時にdevelopブランチをマージしたらコンフリクトが起こるってことですよね。

あんまり、便利なコマンドではないなと思ったんですが、どう思われますか


CC BY-SA 3.0
2017-05-24T05:42:03.837
34976
2017-08-15T03:01:54.680
2017-05-24T06:43:47.937
23264
23264
question
git
Gitでマージの利便性がよくわからない。リベースとかチェリーピックは便利だと思う


ようこそGitの世界へ！

>
> マージの使い所って、developブランチに移動して例えばsampleディレクトリの中にNewsample.txtというファイルを作成して、それをmasterに取り込むって使い方しかできない

ご質問を拝見して  
質問者様が一つ認識違いをしているのかなと思ったことは、  
衝突が発生＝マージができない。  
ではないです。  
衝突が発生したあとに、衝突を解消することでマージを完了することができます。

マージでの衝突を解決する  
<http://www.backlog.jp/git-guide/stepup/stepup2_7.html>

たとえ同じファイルで似たような修正をしたとしても、  
マージ作業でどちらかをコミットすることもできますし、逆に全く違う内容でコミットすることもできます。

※質問が編集されたので追記

> masterブランチにコンフリクトせずにマージを行いたければ

コンフリクトせずにマージをすることは並行開発する上では不可避です。  
もちろん、常に関係者がコミュニケーションをとって、Git上でコンフリクトが起こらないように調整しながら開発することも可能ではありますが、それはあくまでGit上でコンフリクトが発生していないだけでプロジェクト上ではコンフリクトが起きています。


CC BY-SA 3.0
2017-05-24T05:54:16.120
34977
2017-05-24T07:23:26.843
2017-05-24T07:23:26.843
22665
22665
34976
answer


提示された例ですと単純に **行の書き換え** とみなされてコンフリクトは発生しないかと思われます。  
想定されているのは以下のような手順ではないでしょうか。

  1. masterブランチでsample.txtを空のファイルとして作成
  2. developブランチに切り替えてsample.txtに"hello, develop"と書いてコミット
  3. masterブランチに戻りsample.txtに"hello, master"と書いてコミット
  4. masterブランチにdevelopブランチの内容をマージ(ここでコンフリクトが発生)

コンフリクトが発生するのは「同じ個所(行)に対する編集が同時に行われた場合」です。  
実際のマージは別のブランチで **追加編集** した分を取り込むと考えるとイメージし易いのでは。

  1. masterブランチでsample.txtに"hello, master"と書いてコミット
  2. developブランチに切り替えてsample.txtに"hello, develop"と **追記** してコミット
  3. masterブランチに戻りdevelopブランチの内容をマージ(コンフリクトは発生しない)


CC BY-SA 3.0
2017-05-24T06:31:52.800
34979
2017-05-24T06:31:52.800
3060
34976
answer


マージすると競合が発生する、ではなく、競合する変更をマージしようとしているのです。本来なら手動で解決すべき競合を、ある程度自動で解決してくれるのがマージツールです。

現実的には、ソースコードを並行して作業すると言っても大抵は別ファイルや、同じファイルでも別の箇所を変更することになるので、これらは git merge
が自動的に処理してくれます。自動処理ができないような競合は手動で解決しますが、競合してる個所をマークしてくれているので楽です。それも大変そうなら相手の作業が終わるのを待ってから変更を加えればよいです。

というわけで、git merge は便利に使ってますね。

コミット単体の差分を適用する cherry-pick やそれを連続して行う rebase と、まとめてマージを試みる merge
では仕組みが異なるので、前者の方が楽という場合もあるのかもしれませんが...むしろ個別に適用することで個別に競合が発生しがちなので、merge
で最後にまとめて競合解決する方が楽な場面の方が多い印象です。

それよりも、merge コマンド（でfast-
forwardでないマージ）の場合はマージコミットが作成されるので、どこから派生した何をいつマージしたのかが記録として残るという利点があります。逆にマージコミットを作りたくない場合はrebaseしますし、特定のコミットだけを取り込みたい場合はcherry-
pickを使う。こういった使い分けが一般的かと思います。

ちなみに質問に書かれた sample.txt の例を手元で試してみましたが、merge でも cherry-pick でも競合を自動解決できないですね。


CC BY-SA 3.0
2017-05-24T10:45:59.090
34985
2017-05-24T10:45:59.090
8000
34976
answer


本質的に、マージという仕組みを git が採用していることによって得られる利点は、親を２つ持つコミットを作成できることです。

どういう時に、こういったものが欲しくなるかというと、例えば既存のレポジトリをフォークして何かを作る時などに便利です。

  * 既存のレポジトリは、既存のレポジトリで、その master branch は積み上がっていく。
  * フォークしたタイミングで、自分の master が、その時の既存レポジトリの master から作成される。
  * 自分は master にて開発を続ける。定期的に、 origin/master を自分の master にマージしていくことで、フォーク元の変更を吸収できる。

２つの親をコミットが持てることによって、コミットグラフに柔軟性を持たせることができ、コードの管理がより自然にできるようになります。（一直線のコミット履歴しか持てない場合に比べて)


CC BY-SA 3.0
2017-07-06T17:25:39.263
36162
2017-07-06T17:25:39.263
754
34976
answer


> あんまり、便利なコマンドではないなと思ったんですが、どう思われますか

ご質問に端的に回答を書くと

  1. コンフリクトしない状況下では非常に便利です。
  2. コンフリクトする情況では、コンフリクトしてることが分かる点が利便なところです。

コンフリクトは自動的には解決できない問題なので、ツールとしてはこれ以上の機能は必要ないと思いますね。


CC BY-SA 3.0
2017-08-15T03:01:54.680
37202
2017-08-15T03:01:54.680
5008
34976
answer