質問: 複数人が同一ブランチで作業をしていて、共有ファイルでよく競合が発生してしまいます。 作業IDEはECLIPSEです。 マージツールなどで競合の解決をしているのですが、そうなるとコミットログが複数発生してしまいます。 ![競合を解決して作業を続行したときのログ](https://i.stack.imgur.com/XL3Qx.png) 赤枠の部分を1つのコミットとしてまとめたいと思うのですが、そのようなことは可能でしょうか? 操作手順は・・・ 1. (私)ローカルリポジトリでAファイルを作業 2. (別の人)がAファイルをリモートリポジトリにプッシュ 3. (私)最新をプルすると競合が発生 4. (私)Aファイルをコミット 5. (私)競合解消作業をしてコミット(マージツールを使って手動で) 6. (私)引き続き作業 7. (私)プッシュ完成なのでコミット 8. (私)リモートへプッシュ 8の段階で4と5と7を1つのコミットにまとめたいので対話式リベース(スカッシュ)を試みましたが 出来ませんでした・・・ ※5の手順書き直しました! このような場合、競合解決の方法は私の手順であっているのでしょうか? また図のように複数のコミットをまとめる行為は通常しないものでしょうか? Git初心者で初歩的な質問となっていますが、ご教授のほどおねがいします。
回答: * `git pull`は`git fetch` + `git merge`を行うので、pullの代わりに`git fetch`を使いましょう。 (`fetch`は履歴情報だけを取得して、自動での`merge`は行いません) * `pull`または`fetch`のどちらを使う場合でも、なるべくリモートからの同期を行う前に作業ディレクトリはクリーンな状態にしておきましょう。 + コミット前であれば`git stash`で退避を + 頻繁に競合が発生しそうなら、予め作業ブランチを切っておく * 競合が発生した場合には、`merge`でも`rebase`でも競合箇所がマークされるはずなので、競合した個所を適切に修正すれば`rebase`でもコミットできるはずです。 (今現在実行されている手順だと、競合が発生した場合に「競合を解消するためのコミット」を作っているということですよね?) **追記** コマンドペースかつ説明のために冗長なやり方になっている部分があるかもしれませんが、`rebase`のイメージを掴んでもらえればと思います。 この場合の`rebase`は「枝分かれした部分を履歴の先頭に付け替える」ために使用します。 あなたがローカルの`master`でコミット(D)を作成しているうちに、リモートの`origin/master`でも別のコミット(C)が作成され、履歴が分岐してしまったとします。 ``` C origin/master (He) / A---B---D master (You) ``` 自分の作業した分を別のブランチ`topic`に切り替えます。 `$ git checkout -b topic ; git checkout master` ``` C origin/master (He) / A---B---D master,topic (You) ``` ローカルの`master`を競合が起きた時点まで戻します。`HEAD~`で「ひとつ前のコミットまで」、なので必要に応じて繰り返す。 `$ git reset --hard HEAD~` ``` C origin/master (He) / A---B master \ D topic (You) ``` `origin/master`の内容をローカルの`master`に反映します。 `$ git pull` ``` A---B---C master \ D topic (You) ``` 自分の作成したコミット(D)を`rebase`で`master`の先頭に付け替えます。 `git checkout topic ; git rebase master` 競合が起きているならここで解消を行わないと、改変後のコミットが確定しません。 ``` A---B---C master \ D' topic (You) ``` `topic`ブランチを`master`に`fast-forward`で`merge`すればコミットが一直線に並ぶはずです。 (fast-forward = mergeコミットを作らない) `$ git merge --ff topic` ``` A---B---C---D' master ```