GitHub でのチームの共同作業

学習の目的

この単元を完了すると、次のことができるようになります。

  • GitHub ワークフローをチームの効率的なブランチ戦略に変換する。
  • GitHub のマージ競合を解決する。
  • 単一の作業単位を表すアトミックコミットを作成する。

GitHub のブランチ機能のイラスト。

機能するブランチ戦略

独自で作業する場合の GitHub の簡単なサンプルフローを実行しましたが、このワークフローがチームではどのように機能するのかを想像してみてましょう。ブランチ、コミット、およびプル要求の数が、チームの人数や進めている開発の数に応じて倍増します。現在までに多数のチームがこれを経験しており、成功パターンが蓄積されています。

一般にブランチは、1 つの機能を完成させる目的で短期的に使用され、マージ後に削除されます。ブランチを短期的に用いることで混乱を防ぎ、コードを最新の状態に保ち、開発者がプロジェクトを反復的な方法で改良できるようにします。

長期的なブランチは、慎重に使用しなければ問題が生じるおそれがあります。開発ブランチや、コードに複数の開発レベルが必要な状況などでは、長期的なブランチが適していることもあります。長期的なブランチの問題の大半は、開発者の各ブランチが最新バージョンでないため不必要なマージ競合や混乱、作業が生じることに起因します。ブランチワークフローを複雑にすれば問題が解消されるように思えるかもしれませんが、複雑になり過ぎることが少なくありません。GitHub フローはシンプルなほど効率的に機能します。

ブランチについてチームに以下のような質問をします。

  • どのブランチ戦略を採用するのか?
  • どのブランチをマスタにするのか? リリース済みのコードであるブランチはどれか?
  • ブランチに命名規則を採用するのか?
  • ラベルと担当者をどのように使用するのか?
  • マイルストンを使用するのか?
  • プロジェクトボード (プロジェクト) を使用するのか?
  • イシューまたはプル要求に必須テンプレート/要素を設定するのか (出荷チェックリストなど)?
  • プル要求にサインオフをどのように表示するのか?
  • プル要求を誰がマージするのか?

前述のとおり、ブランチの最大のメリットは、安全な場所で変更を行えること、そしてプル要求でレビューやテストを実施できることです。チームがブランチに何を期待しているのかを判断したら、できる限りコンパクトでわかりやすいものにします。コラボレーションを重視します。

マージ競合の処理

チームで共同作業するときに (時として単独で作業するときにも)、マージ競合が生じることがあります。最初はマージ競合に怖気づくかもしれませんが、実際のところ、ごく簡単に解決できます。 

では、マージ競合を作り出して、どうなるかを見てみましょう。

コミットが競合している複数のブランチの作成

ご存知のとおり、マージ競合が生じるのは、別々のブランチの同じファイルの同じセクションに複数のコミットが存在する場合です。そこで、競合の解決を練習するために、競合を設定してみましょう。

  1. マスタから、新しいブランチ (new-branch-1) を作成し、README.md ファイルに変更を加え、プル要求を作成します。
    1. git checkout -b new-branch-1」コマンドを入力します。
    2. リポジトリの README.md ファイルに変更を加えます。どの行を変更したのかをメモしておきます。
    3. new-branch-1 で、変更を加えてコミットします。
      1. git add README.md コマンドを入力します。 
      2. git commit -m "Changes to the README"」コマンドを入力します。
        注意: 通常の操作では、マスタに直接コミットすることはお勧めしません。ここでは、マージ競合をすばやく作成するために直接コミットしています。
    4. git push -u origin new-branch-1 で、ブランチをリモートリポジトリにプッシュします。
    5. GitHub を開いて、このコミットのプル要求を作成します。
  2. ここで、次のブランチおよびプル要求を作成するために、もう一度マスタにチェックアウトします。
    git checkout master
  3. 新しいブランチ (new-branch-2) を作成して、同じファイルに変更を加え、プル要求を作成します。
    1. git checkout -b new-branch-2」コマンドを入力します。
    2. README.md ファイルの同じ行に変更を加えます。
    3. git add README.md コマンドを入力します。
    4. git commit -m “More changes to the README”」コマンドを入力します。
    5. git push -u origin new-branch-2」コマンドを入力します。
    6. GitHub で、プル要求を作成します。

1 つのプル要求のマージ

この時点では、まだどちらのブランチにもマージ競合が表示されていません。GitHub で、1 つ目のプル要求を (new-branch-1 から) マージします。

他のブランチの競合の解決

new-branch-1 のプル要求をマージしたら、new-branch-2 のプル要求に移動します。 

GitHub のマージ競合を示すスクリーンショット。

マージ競合が生じていることがわかりますね。焦ることはありません。解決できます。マージ競合がどのくらい複雑なのかによって、GitHub のブラウザで解決可能な場合もあれば、ローカルで解決する必要がある場合もあります。

ローカルで解決するには、マスタをブランチにマージして、競合を解決してからマージを完了します。

  1. git checkout new-branch-2 で、競合のあるブランチにチェックアウトします。
  2. git pull で、ローカルリポジトリを最新の状態にします。
  3. git merge origin/master で、マスタを機能ブランチにマージします。マージ先はリモート追跡ブランチであって、マスタのローカルコピーではありません。これは、pull コマンドによってリモートブランチと現在開いているブランチは更新されているものの、マスタが更新されていないためです。
  4. 競合の存在が示されていれば OK です! git statusと入力して、どのファイルに競合があるのかを確認します。Unmerged Paths の下に、競合のあるファイルがリストされます。
  5. テキストエディタで該当するファイルを開き、マージ競合のマーカー(<<<<<<<, =======, >>>>>>>)
  6. ブランチの両方のバージョンのコードが表示されています。残すコードを選び、もう一方を削除します。Git によって作成されたマージ競合のマーカーを削除して、変更を保存します。
  7. マージ競合を解決するために保存された変更を追加してコミットします。
    1. git add README.md コマンドを入力します。
    2. git commit -m “Commit to resolve merge conflict”」コマンドを入力します。
  8. git push で、機能ブランチをリモートにプッシュします。
  9. GitHub のプル要求に戻ります。この時点でプル要求に競合はありません。競合のないブランチのスクリーンショット。
  10. プル要求をマージします。

上記のブランチを処理したら、GitHub の該当するブランチを削除し、git checkout mastergit pull コマンドを使用してローカルリポジトリを同期させます。

アトミックコミットの作成

参照可能で有益なプロジェクトの履歴を作成するにあたって、重要な要素となるのが、アトミックコミットの作成です。

理想とするのは、履歴の内容を確認したり変更したりする必要がない世界です。残念ながら、そんな理想的な世界は望めないため、必要に応じてバージョン管理によって変更履歴を確認できるようになっています。コミットはそれぞれ、小規模で論理的な変更単位であり、リポジトリのストーリーを伝えるものです。

では、アトミックコミットの作成に役立つ git add --patch というコマンド (短縮形は git add -p) の使い方を練習してみましょう。このコマンドは、ファイルの各部をステージングエリアに追加することができ、真に論理的な変更単位をコミットする場合に役立ちます。

  1. bigFile.md をコンピュータにダウンロードします (場合によっては、右クリックして [対象をファイルに保存] を選択する必要があります)。
  2. GitHub で、bigFile.mdbest-repo-ever リポジトリのマスタブランチにアップロードします。
    1. [Upload files (ファイルをアップロード)] をクリックします。
    2. コンピュータで bigFile.md を選択します。
    3. [Commit directly to the master branch (マスタブランチに直接コミット)] を選択します。
    4. [Commit changes (変更をコミット)] をクリックします。
  3. ローカルのマスタリポジトリが最新の状態であることを確認します。
    1. git checkout master」コマンドを入力します。
    2. git pull」コマンドを入力します。
  4. git status で、Git で追跡している内容を確認します。
    コミットするものが何も存在しないことがわかります。
  5. bigFile.md の 1 行目と 100 行目に変更を加えます(変更内容は何でも構いません)。
  6. git add -p に --patch フラグを設定して、いくつかのファイルの一部をステージングエリアに移動します。
  7. [y] を押してハンクをステージングします。これは変更単位に対する Git 言語です。

ハンクにどのようなオプションがあるのか気になる場合は、? を使用すると、ハンクの上にオプションリストが表示されます。