グループ用GitHubリポジトリの作成
やること:
- グループ用assignmentをacceptして,グループ用リモートリポジトリをGitHub上に作る。
- 「git clone」でメンバー各自のローカルリポジトリを作る。
- (作業コピー上でプログラム作成,commit, push。)
- 必要に応じ,他のメンバーの編集結果をpull。
参考資料:
オンラインマニュアル:
git help コマンド名
(例えばgit help commit
)または
man git-コマンド名
(例えばman git-commit
)
1. グループ用リポジトリの作成
チーム名の修正や所属するチームの変更はできないので,注意して入力・選択すること。
- 2人以上3人以下のグループを決める。チーム名(英数字列)を決める。
- 代表者1名が下記のURLを開き,「Create a new team」欄にチーム名を入力して「+Create team」ボタンを選択する。
https://classroom.github.com/a/tTjppKKC - 他のメンバーも上記URLを開き,「Join an existing team」欄のチームから自分のチームを探し,「Join」を押す。
2. ローカルリポジトリの作成 (clone)
以下の作業はメンバー全員がそれぞれ行う。リポジトリ名が違うこと以外は「2-a. Gitを使った開発作業」の「2. ローカルリポジトリの作成 (clone)」と同じである。
なお,下記2.のgit clone
は,全員が同時に行うとサーバの応答が遅くなるので,授業中の指示に従って順番に行うこと。
- 上記で作成したGitHub上の自チームのリポジトリ名を確認する。
q1-i386-チーム名
となっているはず。 次のステップ2.で使うclone用URLは以下のようになる。
https://github.com/kut-info-pl2/q1-i386-チーム名.git
- 端末にて,下記のように
git clone URL
を実行する。必ずこれまでのリポジトリの外のディレクトリで実行すること。$ cd どこか/git -- リポジトリの外に移動 $ ls -- リポジトリの中でないことを確認 q0-warmup-HogeUser/ $ git clone https://github.com/kut-info-pl2/q1-i386-HogeTeam.git Cloning into 'q1-i386-HogeTeam'... remote: Enumerating objects: 14, done. remote: Counting objects: 100% (14/14), done. remote: Compressing objects: 100% (10/10), done. remote: Total 14 (delta 3), reused 7 (delta 1), pack-reused 0 Unpacking objects: 100% (14/14), done. $ cd q1-i386-HogeTeam -- 作業コピーにcdする $ ls README.md chap6/ -- 作業コピー中のファイルとディレクトリ $ ls -aF ./ .git/ README.md ../ .gitignore chap6/
(1
(いち)とl
(エル)などの似ている文字に注意。pl2
(ピー エル 2)は programming lab II(= 実験第2)を表す。)
q1-i386-チーム名
というディレクトリの中に作業コピーが取り出される。
3. 編集作業, コミット, push
ファイルの編集, コミット, pushの方法はこれまでと同じだ。 ただし,他のメンバーもリモートリポジトリ中のファイルを変更することに注意が必要だ。 以下,注意すべき事柄を説明する。
他メンバーのコミットによるpushの失敗
自分がclone(またはpull)してから自分がpushするまでの間に,他のメンバーがリモートリポジトリを変更 (push) すると,自分はpushできなくなる。
この場合,まずgit pull --rebase
を行って他メンバーの編集結果を自分のローカルリポジトリに取り込んでから,pushしなければならない。
git pull
については下の「4. 他のメンバーの編集結果のpull」も参照。
実行例(gitの出力メッセージを適宜省略している):
$ git commit -- ローカルにcommit
[master a07ee6e] print_eax.sを作成
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 chap6/print_eax.s
$ git push -- リモートにpush... 失敗
To https://github.com/kut-info-pl2/q1-i386-HogeTeam.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/kut-info-pl2/q1-i386-HogeTeam.git'
$ git pull --rebase -- pushの前にpull
pullした後,ログを見ると,他メンバーのコミットが取り込まれ,その後に自分のコミットが追加されたことを確認できる。
$ git log --oneline
1e31ddc print_eax.sを作成
9c33da0 test_print.sを作成
31073cb Initial commit
なお,この時点ではまだ自分のコミットはリモートリポジトリに追加されていない(「リモートの内容をローカルに取り込んだ」という状態)。この後 push することで,自分のコミットがリモートリポジトリに追加される。
4. 他のメンバーの編集結果のpull
上でも書いたように,下記を実行すると,リモートリポジトリの内容が自分のローカルリポジトリに反映される。
$ git pull --rebase
まだpushしていない自分のコミットがある場合,リモートリポジトリの内容を取り込んで,その後に自分のコミットが追加される。
(補足:「他メンバーのコミットを取り込んでその後に自分のコミットを追加する」ということは,実は「ローカルリポジトリのコミットの歴史(親子関係)を修正する」ことを意味する。すなわち,あたかも他メンバーの編集作業が終わってから自分が編集したかのようにコミットを書き換えている(これをrebaseと言う)。これを行うために,git pull
に --rebase
オプションを付けている。もし,--rebase
オプションを付けずに git pull
を実行した場合は,「歴史を修正」せずに,分岐した歴史の「合流点」(マージコミット)を追加する。
詳しくはこのページの末尾の付録を参照。)
(補足2:--rebase
オプションを付けずにpullした場合,マージコミットに対するログメッセージの入力を要求される。“Merge branch 'master' of ...”というデフォルトのメッセージのままでよければ,メッセージを保存してエディタを終了すればよい。)
他のメンバーと自分が同じファイルの同じ箇所を編集していた場合,競合 (conflict) という状態になって pull に失敗 する。 この場合については次の節を参照。
編集の競合 (conflict)
(なるべく無い方がよいが)他メンバーと自分が同じファイルの同じ箇所を変更している場合,「競合」というエラー状態になる。 pullが 途中で止まった 状態になっているので,以下のどちらかを行わないと他の作業ができない。
- 競合箇所を手で修正した後,pullを再開する。これについては下で説明する。
git rebase --abort
を実行してpullを中止する(pull実行前の状態に戻る)。(pullできない問題は解決しないが,ひとまず元の状態に戻るので,状況が複雑ならこちらの方が安全。)
以下,競合箇所を手で修正する手順を説明する。
競合が起きると,そのファイル中に下記のような形式で競合内容が書き込まれる。当然この部分を書き直さないと正常にアセンブルやコンパイルはできないので,必ず修正すること。
<<<<<<< HEAD
mov eax, 0x10
=======
mov eax, 16
>>>>>>> e687d558d528f86a7e2708aaf1f015f948d9465a
<<<<<<< HEAD
から=======
までが自分の編集内容,=======
から>>>>>>> コミット番号
が他メンバーの編集内容だ。
修正(及び途中で停止したpullの回復)の手順は以下のようになる。
- どちらかの編集内容を選ぶなり,両方を合わせた内容にするなりして編集した後,
<<<<<<< HEAD
等の余分な行は消す。 - 修正後のファイルを
git add
する。 git rebase --continue
を実行。
(注: --rebase
オプションを付けずにpull
して競合が起きた場合は,3.で git rebase --continue
ではなく git commit
を実行する。)
付録: pull と pull --rebase
オプションを付けずに git pull
を実行するとマージ (merge) が行われ,
--rebase
オプションを付けて git pull
を実行するとリベース (rebase) が行われる。
$ git pull -- リモートとローカルをmergeする
$ git pull --rebase -- ローカルをrebaseする
マージは「マージコミットを追加し,分岐した編集履歴を合流」する。 リベースは「リモートリポジトリの最新コミットの後に自分の編集履歴を移動」する。
例えば下図のように,あるコミット E の後にコミット F, G を行ったが,その間に他メンバーがコミット A, B, C を行ってリモートリポジトリにpushしていたとする。
before)
A---B---C 他メンバーのコミット
/
D---E---F---G 自分のコミット
pullを行うと,いずれにせよリモートのコミット A, B, C がローカルにダウンロードされるが,それらと自分のコミット F, G との結合の仕方が --rebase
オプションの有無によって異なる。
オプションなしでpullを行うと,マージコミット H が追加される。また,このとき,H のログメッセージの入力を要求される(“Merge branch 'master' of ...”というデフォルトメッセージが表示されるので,それをそのまま使えばよい)。H は,A, B, C で行われた変更と F, G で行われた変更の両方を反映したコミットになる。
merged)
A---B---C
/ \
D---E---F---G---H
pull --rebase
を行うと,コミット F, G を,コミット C の後に行われたかのように修正する(F の親 (base) を変更するので rebase)。
rebased)
A---B---C
/ \
D---E F'--G'
リベースを使うと,マージと違って変更履歴の分岐・合流がなくなり,また余分なマージコミットがなく簡潔になって,開発の流れを追いやすくなる。分岐・合流の記録を残したい場合はマージ,残したくない場合はリベースを使うとよい(この授業では,ほぼ常にリベースでよいと思う)。