Ruby合宿2021春
Gitの使い方説明
Gitとは?
• オープンソースの「バージョン管理システム」
• Windows上で使う場合は、「Git for Windows」をインストールする
Git for Windows導入後最初にやるべき事
• 氏名とメールアドレス、それと使用するエディタあたりをGitに
教えておく
> git config --global user.name “foo bar baz"
> git config --global user.email [email protected]
> git config --global core.editor notepad
※ 「メモ帳」はさすがに…という場合は、好
きなエディタをインストールしておき、その
パスを設定する
バージョン管理とは?
• ファイルの変更履歴を管理すること
• ファイルとは
• ソースコード(テキスト)
• バイナリ(画像など)
ソースコードの成長記録のようなもの
ざっくりと感覚的に表現すると…
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/7 謎のバグに遭遇…。 時間軸 ソースコードの歴史が積み重なってゆく何が嬉しいのか?
• いつ、誰が、どんな変更をしたかが全部記録されているので、
歴史を辿りやすい
• 記録されている変更点であれば、いつでもその時点の状態に戻
すことができる
• リポジトリ(変更点を記録するデータベース)が共有できる場
合、複数人で1つのソースコードを開発する道具として利用可
能
用語紹介
• リポジトリ
• 変更履歴を保存する入れ物となるデータベース
• Gitの場合、ローカルリポジトリとリモートリポジトリの2種類があるが、詳細は
後述。ここではローカルリポジトリを説明している
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/7 謎のバグに遭遇…。 管理対象ソースコードのトップディ レクトリに.gitという名前で作られるローカルリポジトリを作成する
• 任意のパスに、空ディレクトリを作る(名称は仮に
「mygame」とする
• mygameディレクトリをカレントとし、以下のコマンドを実行
する
• git init
• ブランチ
• 変更点のまとまりのこと(作業履歴)
• Gitリポジトリを作ると「master」という名前のブランチが1つできている。
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/7 謎のバグに遭遇…。 変更点1 変更点2 変更点3 master以下のコマンドで現在のブランチ一覧が確認できる
> git branch
どんなことができる?
2021/3/5 初めの第一歩
require ‘dxruby’
記録!
変更内容を記録する
(git add / git commit)
2021/3/5 初めの第一歩 require ‘dxruby’ Window.loop do end 記録! 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/5 初めの第一歩 require ‘dxruby’ player = Player.new(100, 100) Window.loop do player.update player.draw end 記録! 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/7 謎のバグに遭遇…。
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/7 謎のバグに遭遇…。 頑張ってみたけど、謎 のバグが消えない…。 心が折れました…。 2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! この修正は無かったこ とにして、3/6の状態か らやり直そう!
変更内容を消して無かったことにする
(git reset)
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/8 無事にキャラ表示できるよ うになった!2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/7 謎のバグに遭遇…。 頑張ってみたけど、謎 のバグが消えない…。 心が折れました…。 2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! この修正は無かったこ とにして、3/6の状態か らやり直そう!
変更内容を追加して無かったことにする
(git revert)
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/8 無事にキャラ表示できるよ うになった! 2021/3/7 謎のバグに遭遇…。 2021/3/7 謎のバグに遭遇…。 Revert: 2021/3/7 謎のバグに遭遇…。 対象コミットの内容を 消滅させる「逆」内容 のコミットを追加する2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! 2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! master master 2021/3/7 実験的にウィ ンドウサイズ変更 branch1 2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! master 2021/3/7 実験的にウィ ンドウサイズ変更 branch1
時系列を分岐(枝分かれ)させる
(git branch)
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! master 2021/3/7 実験的にウィ ンドウサイズ変更 branch1 masterブランチをカレントとして以下 を実施
> git merge branch1
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! master 2021/3/7 実験的にウィ ンドウサイズ変更 branch1 2021/3/9 branch1の変更を取り込み! 2021/3/8 require不足に対応 2021/3/8 require不足に対応 2021/3/8 ESCキーでアプリ終了に 2021/3/8 ESCキーでアプリ終了に Branch1の変更履歴がmasterに合流する。
時系列を再統合させる
(git merge)
2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! master 2021/3/7 実験的にウィ ンドウサイズ変更 branch1 branch1ブランチをカレントとして以 下を実施
> git checkout branch1 > git rebase master
2021/3/8 require不足に対応 2021/3/8 ESCキーでアプリ終了に
枝分かれした時点を変える
(git rebase)
branch1がmasterから 枝分かれした時点はこ こ branch1はこの変更を 知らない(枝分かれし た後にできたコミット だから) 2021/3/5 初めの第一歩(ほぼ空っ ぽ) 2021/3/6 ウィンドウらしきものが出 るようになった! master 2021/3/7 実験的にウィ ンドウサイズ変更 branch1 2021/3/8 require不足に対応 2021/3/8 ESCキーでアプリ終了に branch1の枝分かれ元となっ たコミットが変化する (rebase先ブランチ、つま りmasterの最新コミットに なる)競合の解消
• ブランチを分けて並列に開発をしていると、修正箇所が被るこ
とが往々にして起こる
• これが起こると、マージやリベース時に「競合」という状態に陥り、
自動的なマージ・リベースが行えない
• 従って、競合が起きると、その解消は人間(作業者)が行わざるを得
なくなる
• 例えば、masterブランチとbranch1で以下のような競合が発生
したとする
require 'dxruby'
Window.loop do
end
最初のコミット master branch1require 'dxruby’
Window.width = 1024
Window.height = 768
Window.loop do
end
branch1のコミット1require 'dxruby’
Window.width = 800
Window.height = 600
Window.loop do
end
2つ目のコミット こっちは800x600と指定して るのに… こっちは1024x768と変更し ているどちらの修正が「正」なのか、Gitが自動判定することは不可能
実際にmergeしてみると…
これから何度も見るであろう、「CONFLICT」(競合)のログ…
解消すべく、ソースコード(ログにある「main.rb」)を開くと…require 'dxruby'
<<<<<<< HEAD
Window.width = 800
Window.height = 600
=======
Window.width = 1024
Window.height = 768
>>>>>>> branch1
Window.loop do
end
競合している箇所をGitが新設にも示してくれているでは ありませんか。 ※ ここで、HEADとはマージ対象であるmasterを指す ※ 競合が起きているファイルは、「git status」コマンドでも確認可能。 競合している場合、 Unmerged paths:(use "git add <file>..." to mark resolution) both modified: main.rb
競合箇所を正しいコード(あるべき姿)に修正
require 'dxruby'
<<<<<<< HEAD
Window.width = 800
Window.height = 600
=======
Window.width = 1024
Window.height = 768
>>>>>>> branch1
Window.loop do
end
require 'dxruby'
Window.width = 800
Window.height = 600
Window.loop do
end
今回はHEAD側を正としてみる 後は普通に修正結果をgit add → git commit すればOK• では、rebaseで競合した場合はどうするのか?
マージの時とは微妙に違うけど、やはり「CONFLICT」の文字が…
require 'dxruby' <<<<<<< HEAD Window.width = 800 Window.height = 600 ======= Window.width = 1024 Window.height = 768>>>>>>> add01e5... branch1 commit1 Window.loop do
end
マージの時と似たような感じでGitが競合箇所を指摘 してくれている。
競合箇所を正しいコード(あるべき姿)に修正
require 'dxruby' <<<<<<< HEAD Window.width = 800 Window.height = 600 ======= Window.width = 1024 Window.height = 768>>>>>>> add01e5... branch1 commit1 Window.loop do end require 'dxruby' Window.width = 800 Window.height = 600 Window.loop do end 今回もHEAD側を正としてみる 競合状態を起こしている ファイルを確認して修正を 施し… 修正したファイルをgit add する(コミットはしない点 に注意) そして、git statusがこのよ うに表示をするまで修正を 繰り返す 最後に「git rebase – continue」をして確定する
リモートリポジトリ
• ローカルPCの作業ディレクトリにある「.git」ディレクトリの
ことを「ローカルリポジトリ」と呼ぶ
• 対して「リモートリポジトリ」とは、ネットワークを介した外
部(リモート)に存在するリポジトリである
• リモートリポジトリを提供するネットサービスは多数存在する
が、有名なものでは「Github」などが挙げられる
リモートリポジトリのイメージ
ローカルリポジトリ「.git」
master
branch1
Remote repository 「origin」
Fetch: [email protected]:XXXX/YYYY
Push: [email protected]:XXXX/YYYY
Github上のリモートリポジトリ「XXXX/YYYY」master
branch1
Github上のリモートリポジトリ 「XXXX/YYYY」を、「origin」とい うローカル名称で認識する Github上の「master」ブランチをト ラッキングする Github上の「branch1」ブランチを トラッキングする• 先にローカルリポジトリがあっても良いし、リモートリポジト
リが先にあっても良い
• リモートリポジトリから新しくローカルリポジトリを作る場合
は、「git clone」コマンドを使用する
• これだけでリモートリポジトリの設定が完了したローカルリポジトリ
が生成されるので、非常に便利
master ローカルリポジトリ リモートリポジトリ master master ローカルリポジトリ リモートリポジトリ master pull
リモート側の変更履歴をローカル側で受け取る
(git pull / git fetch)
master ローカルリポジトリ リモートリポジトリ master master ローカルリポジトリ リモートリポジトリ master push
ローカル側の変更履歴をリモート側に送る
(git push)
複数人でのリポジトリ管理
• 1つのリモートリポジトリを、開発メンバー全員で共有するこ
とで、チーム開発のプラットフォームとして活用できる
Github上のリモートリポジトリ メンバーAさんのローカル リポジトリ メンバーBさんのローカル リポジトリ メンバーCさんのローカル リポジトリ git clone git clone git cloneチーム開発のスタイル
• 以下は絶対的な縛りではないが、本合宿で推奨するパターン
• masterブランチの管理はチームリーダーが一元的に行う
• 各メンバーは、自分の担当作業毎に「作業ブランチ」を作成し、それ
をリモートリポジトリに「Push」してメンテナンスする
• 作業ブランチの内容がまとまったところで、Githubの機能である
「Pull Request」を作成し、チームリーダーにマージ依頼を行う
• チームリーダーはPull Requestの内容を確認し、問題無ければmaster
ブランチにマージする
Pull Requestについて
• 作業ブランチの成果をmasterに取り込むために使える、Github
のWeb UI上の便利機能
• 作業の流れ
• 作業ブランチの持ち主(作業者)が、自分のローカルリポジトリの作業ブランチ
をリモートリポジトリ(origin)に「git push」する
• 作業者が、GithubのWeb UIを開き、当該作業ブランチ(リモート側)をベース
に「Pull Request」を作り、masterブランチの管理者にPull Requestを送付する
• masterブランチ管理者は、Pull Request記載の変更内容を確認し、問題なければ
「マージ」し、作業ブランチの成果をmasterブランチに取り込む
• 各作業者は、自分のローカルリポジトリのmasterブランチで、「git pull」する
• すると、マージされた最新masterの内容が落ちてくるので、適宜自分の作業ブランチ
にmasterをマージする
• もしくは「git rebase」してmasterに追随する
Pull Requestを使った作業の例
• 作業者Aさんがまずgithub上のリモートリポジトリを「git clone」する
• 作業ディレクトリは仮に「C:¥rubycamp¥src」とする
• リモートリポジトリ名は仮に「git_tutorial」とする(ユーザー名は仮に「XXXX」とする)
git clone [email protected]:XXXX/git_tutorial
C:¥
├─ rubycamp
├─ src
├─ .git
git branch issue1
git checkout issue1
~ 粛々とソースを編集する~
git add .
git commit –m “updated”
git push –u origin issue1
• 作業者Aさんは、自身の作業ブランチを作り、修正・コミットを実施する
• その後、「git push」にてリモートリポジトリに作業ブランチをPushする
リモートリポジトリ「origin」に issue1という名前でブランチを送り 込む
• Githubの当該リモートリポジトリのページを開き、「branches」からPull
Requestを作る
• master管理者がPull Requestを確認し、マージする
※ Web UI上でそのブランチがmasterに対してどの程度変更されたかなどの差分確認もできるので、
大変便利。
• マージされたら、各作業者は自身のローカルリポジトリのmasterを最新化する
git checkout master
git pull
• もし、ローカルリポジトリに過去のmasterから分岐した別の作業ブランチがあったら
• 最新masterの内容を取り込んで追随しておいた方が、後々マージの時幸せになりやすい
git checkout issue2
git rebase master
別作業ブランチ「issue2」を最新masterに追随する場合、2通りの方法があり得る。
git rebaseによる方法
git checkout issue2
git merge master
git mergeによる方法
• もし、Pull Requestで競合が起きたら
競合発生をWeb UIで知らせてくれる
競合箇所を適宜修正 して… 「解決」したことを 知らせよう 解決結果をコミットし てマージ準備完了!無事、競合が無くなっ たことを確認したら…
最後にマージを実行し て終了!