Gitを使った開発作業
(「グループ用GitHubリポジトリの作成」のつづき。)
やること:
- グループ用assignmentをacceptして,グループ用リモートリポジトリをGitHub上に作る。
- 「git clone」でメンバー各自のローカルリポジトリを作る。
- gitコマンドの初期設定をする。
- (作業コピー上でプログラム作成)
- 編集結果をローカルリポジトリにコミット。
- リモートリポジトリにpush(自分の編集結果をリモートリポジトリに送る)。
- (必要に応じ,他のメンバーの編集結果をpull)
参考資料:
オンラインマニュアル:
git help コマンド名
(例えばgit help commit
)または
man git-コマンド名
(例えばman git-commit
)
4. 編集作業
「どのディレクトリのどのファイルをどう編集するか」は各演習課題の説明を読むこと。
第2章の演習1.2-xについては,「chap2」サブディレクトリの中に,指定された名前のソースファイルを作成する。
5. ローカルリポジトリへのコミット
git statusを実行して,変更したファイルを確認する。
$ git status # On branch master # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: README.md # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # 123.s no changes added to commit (use "git add" and/or "git commit -a")
上の例では「(カレントディレクトリの)README.md が変更されている。123.s が新しく作られている」という情報が表示されている。 (末尾の「no changes added to commit」という行に注意。この状態では何もコミットされない。)
コミットしたいファイルに対して git add を実行する。
$ git add README.md 123.s
1ファイルずつgit addしてもよい。一部のみコミットしたい場合はそのファイルだけaddすればよい。
(git addした時点でgit statusを実行すると,状態が変わったことが確認できる。)$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: README.md # new file: 123.s #
(「Changes to be committed:」の下に表示されているファイルがコミット対象。)
- git commit を実行する。
-m
オプションの後に適切なコミットメッセージを記述すること(メッセージが空白を含む場合は引用符'
で囲まなければならない。引用符で囲むよう習慣付けておくのが安全)。$ git commit -m '123.sを作成' [master 9c33da0] 123.sを作成 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 chap2/123.s
参考:
- git addを取り消したい場合は「git reset HEAD ファイル名」を実行する(git status で表示されるメッセージを読めば書いてある)。
- .oファイルや実行可能ファイル (a.out) やEmacsが作るバックアップファイルなどは,特に理由がない限りリポジトリには追加しないのが作法。リポジトリのルートディレクトリの .gitignore というファイルにファイル名を書いておくと,Gitはそのファイルを無視する。
コミットメッセージ
コミットメッセージとは,変更履歴(ログ)に記録されるコメントだ。 git logコマンドを実行すると一覧が表示される。
$ git log
commit 9c33da03e8dbaf1d95cf6a997bc9849ef0f510b2
Author: ytakata69 <takata.yoshiaki@kochi-tech.ac.jp>
Date: Thu Sep 15 11:15:47 2016 +0900
123.sを作成
commit 7ac3bf5bb664c07f47c2471ac3b4fbfe676bc264
Author: ytakata69 <takata.yoshiaki@kochi-tech.ac.jp>
Date: Wed Sep 14 19:58:25 2016 +0900
Add chap2 subdirectory
-- 略 --
-- ログが長い場合「ページ単位で表示」モードになる。スペースキーで次ページに進む。qキーで終了する。
--oneline
オプションを付けると簡潔な表示になる。
$ git log --oneline
9c33da0 123.sを作成
7ac3bf5 Add chap2 subdirectory
23b0570 Add Emacs backup files and LaTeX aux files to .gitignore
85b1bb2 Remove '*.hex' from .gitignore
31073cb Initial commit
「これまでどういう変更を行ってきたか,ログを見れば概ねわかる」ように書くのが適切だ。また,「ある変更を行った時点のファイルを取り出したい」と思ったとき,コミットメッセージを適切に書いていれば,メッセージを検索することで容易に該当コミットを見つけられる。
例えば,「123.sを更新」「123.sを更新」「123.sを更新」…のようなログは適切でない。メッセージが具体的でないのでどういう変更を行ってきたか推測できないし,検索するときにも困る。
6. リモートリポジトリへのpush
$ git push
pushしていないコミットは,他のチームメンバーからも見えないし,成績評価対象にもならない。
コミットするたびにpushする必要はなく,区切りのついた時点でpushすればよい。リモートリポジトリにpushされたコミットの取り消しやコミットメッセージの修正は原則できなくなるので,pushは多少慎重にした方がよい。一方,pushしないといつまでも他のメンバーに修正結果が伝わらないので,pushせずに長く置いておくのもよくない。
他メンバーのコミットによるpushの失敗
自分がclone(またはpull)してから自分がpushするまでの間に,他のメンバーがリモートリポジトリを変更 (push) すると,自分はpushできなくなる。 この場合,まずpullを行って他メンバーの編集結果を自分のローカルリポジトリに取り込んでから,pushしなければならない。
実行例(Gitの出力メッセージを適宜省略している):
$ git commit -m 'hms.sを作成' -- ローカルにcommit
$ git push -- リモートにpush... 失敗
To https://hoge135@github.com/kut-info-pl2/q1-i386-team135.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://hoge135@github.com/kut-info-pl2/q1-i386-team135.git'
$ git pull -- pushの前にpull
上記の状況,つまりリモートリポジトリにもローカルリポジトリにも変更がある状態でpullを実行すると,Gitはmerge(統合)を行う。 すなわち,両方の変更を施した状態にして,自動的にコミットする。 ログを見ると,一番上に自動実行されたコミットが加わっているのがわかる。
$ git log --oneline
e4b5f95 Merge branch 'master' of https://github.com/kut-info-pl2/q1-i386-team1
a07ee6e hms.sを作成
1e31ddc 123.sを作成
7ac3bf5 Add chap2 subdirectory
23b0570 Add Emacs backup files and LaTeX aux files to .gitignore
85b1bb2 Remove '*.hex' from .gitignore
31073cb Initial commit
git logの--graph
オプションを使うと,コミット履歴グラフが表示される。下の実行例のように,コミット7ac3bf5から2つのコミットに分岐し,再度合流していることが確認できる。
$ git log --oneline --graph
* e4b5f95 Merge branch 'master' of https://github.com/kut-info-pl2/q1-i386-t
|\
| * 1e31ddc 123.sを作成
* | a07ee6e hms.sを作成
|/
* 7ac3bf5 Add chap2 subdirectory
* 23b0570 Add Emacs backup files and LaTeX aux files to .gitignore
* 85b1bb2 Remove '*.hex' from .gitignore
* 31073cb Initial commit
この時点ではまだ,自分のコミット(「hms.sを作成」)とmergeコミットはリモートリポジトリに追加されていない。この後 push することで,これら2コミットがリモートリポジトリに追加される。
7. 他のメンバーの編集結果のpull
$ git pull
リモートリポジトリの内容を自分のローカルリポジトリ(と作業コピー)に反映する。
まだpushしていない自分のコミットがある場合,リモートリポジトリの内容と自分のコミットとのマージ (merge) が自動的に行われる。
(あまり無い方がよいが)他メンバーと自分が同じファイルの同じ箇所を変更している場合,マージに失敗する。その場合は競合箇所を手で修正する必要がある。