Bitbucket + EGit^5
チーム開発をしているときに避けられないのが、コンフリクト(conflict;競合)。これはソースをプッシュしようとしたら、他の人も同じ箇所を修正していて、それが先にプッシュされた、という場合発生する。あるクラスの異なるメソッドを編集した、といった場合は、プッシュしたときgitがいい感じで解決してくれる(merge;マージ/併合)ので、コンフリクトにはならない。しかし変更箇所が同じ場合、gitはどちらを残すかのが適切か判断できないので*1、このコンフリクトという状態になる。そしてこのコンフリクトが解消されるまで、プッシュできなくなる。つまり自分の作業内容を、他のチームメンバーに取り込んでもらえなくなる、ということ。コンフリクトが起きたら、その解決を最優先ですべし。
以下はコンフリクトが発生する経緯と、その解決方法の説明。
■想定するシナリオ
ItemDaoクラスに以下のようなsaveメソッドがあった。
public int save(String id) throws DAOException { return 0; }
これをaldebaranさんは以下のように変更した。
public int save(int id) throws DAOException { return 0; }
一方、procyonさん以下のように変更した。結果としては、これを残したい。
public int save(ItemBean item) throws DAOException { return 0; }
流れとしては下表なような感じになる。
# | procyonさん | aldebaranさん |
---|---|---|
0 | プル | プル |
1 | String id → int id へ変更 | |
2 | コミット・プッシュ → 成功 | |
3 | String id → ItemBean item へ変更 | |
4 | コミット・プッシュ → 失敗(コンフリクト) | |
5 | プル | |
6 | コンフリクト解消 | |
7 | コミット・プッシュ → 成功 | |
8 | プル → 成功 |
この例の場合、4でprocyonさんがプッシュする前に、同じ箇所を2でaldebaranさんがプッシュしているのでコンフリクトになる。以下その様子と、解決方法を示す。
1. aldebaranさん 変更
引数をint id へ変更。保存すると[ステージされていない変更]に表示される。
[++]押下→[コミット・メッセージ]入力する。
2. aldebaranさん コミット・プッシュ → 成功
[コミットおよびプッシュ(M)]押下すると、プッシュまで成功する。
3. procyonさん 変更
一方、同じころ、procyonさんもsave()を修正した。
4. procyonさん コミット・プッシュ → 失敗
しかし、[++]押下→[コミット・メッセージ]入力して、[コミットおよびプッシュ(M)]押下したが拒否された。
このnon-fast-forwardというのは、
あなた(procyonさん)がプッシュしようとしたリソース(ItemDAO.java)は、ほかの人(aldebaranさん)が先に更新していて、しかもその更新箇所があなたのとぶつかっていて、どうすればいいかかわからないので、あなたがどうにかしてくれるまで、このプッシュは無かったことにするね(ニッコリ。
ということを表している。これがコンフリクト(Conflict;競合)。こうなったら、できるだけ速やかに、以下のような手順で解消すること。
5. procyonさん プル
まずプル操作で、ほかの人が変更した内容、つまりaldebaranさんがプッシュした内容を自分のEclipseプロジェクトへ取り込む。
プロジェクト・エクスプローラでプロジェクト名 右クリック > チーム(E) > プル(U)を選択。
やはり競合していることがわかる。
6. procyonさん コンフリクト解消
上記プル操作でItemDAO.javaには、競合している内容が取り込まれる。
競合しているのがこの部分。
<<<<<<< HEAD public int save(ItemBean item) throws DAOException { ======= public int save(int id) throws DAOException { >>>>>>> branch 'master' of ... return 0; }
これをコミット・プッシュしたいように編集する。(その前に、この部分をいじった競合相手であるaldebaranさんへ一声かけて確認するのが、いろいろとベターな気がする)
public int save(ItemBean item) throws DAOException { return 0; }
7. procyonさん コミット・プッシュ → 成功
編集後、保存を押すとItemDAO.javaが[ステージされていない変更]に表示されるが、[++]押しても[ステージされた変更]には移らず消える。[コミット・メッセージ]を適宜入力して、[コミットおよびプッシュ(M)]押下する。
今度はプッシュできた。
8. aldebaranさん プル → 成功
この内容を取り込むには、aldebaranさんもプル操作しなければならない。プルするとこのように、procyonさんの編集内容がこちらにも取り込まれる。
コンフリクトは避けがたいが、無用なマージ操作は避けたい。そのためには自分の作業に関係ないファイルやコードはいじらない!が鉄則。もしやっちまって、自分でコンフリクトを解決するのが難しいという場合は、いち早くテクニカルリーダーや講師にHelp!すること。
*1:あとからプッシュしたものを残すのが正しいとは限らないから