社内研修用。
GitとGitHubのさわりだけ。
LastModified: 2017-11-16
- LoremIpsum (GitHub Lecture for sforzando LLC.(ex szk-engineering))
- Remarks
何はともあれ、はじめにGitHubのアカウントを作ります。
アカウントを作ったら、公開鍵を登録します。
ローカル環境の ~/.ssh/config
もこんな感じで変更しておくと良いかも。
Host github-private
User git
Port 22
HostName github.com
IdentityFile ~/.ssh/github-private_rsa
TCPKeepAlive yes
IdentitiesOnly yes
自分のアカウントでレポジトリを作ってみる。
$ git init
誰かのレポジトリをwatchして、どんな風に使ってみるか見てみる。
素敵なレポジトリを見つけたらstarしてあげると開発者は喜ぶ、きっと。
誰かのレポジトリをローカルにcloneしてみる。
$ git clone <url>
<url>
は各レポジトリ画面の右下にある。
gitやhttps、sshなど様々なプロトコルを選べるけど、基本的にどれでもいい。
その下にある"Clone in Desktop"はGitHub謹製のGUIアプリ経由で使う場合。
"Download ZIP"はgit cloneでなく、単にファイルとして欲しい時(gitをインストールしてない環境で、とりあえず見てみたい時など)に使う。
ローカルで加えた変更点をリモートのレポジトリに反映してみる。
{{(何らかの変更) → add(to working tree)}を何回か繰り返してから → commit(to index)}を何回か繰り返してから → push(to remote repository)。
なんでも良いから書き換えてみる。revert/reset(元に戻す)できるのがGitの良いところなので、失敗を恐れずに。 とは言え、README.mdを書き換えるのが一番手ごろ。
README.md(Markdown)ファイルをいじるのにおすすめの環境は…
- Sublime Text 3
- Atom
- Visual Studio Code
GitHubで使えるMarkdown特殊記法も使いこなせるとかっこいい。 checkboxとか。この辺を参照。
https://help.github.com/articles/github-flavored-markdown
Gitでは変更点を追跡するかどうか、add/rmしながら使う。 基本的に全部追跡しちゃえば良い。
$ git add .
追跡中のファイルたちをworking treeって言ったり、追跡状態にあることをstagingって言ったりする。
基本的に全部追跡とは言え、追跡してもしょうがないlogファイルとか不可視ファイルもあるので、ignore(無視)設定しておくと良い。
プロジェクトのルートディレクトリに .gitignore
を作る。
MacOSXだったら、下記は無視しておくと良い。
.DS_Store
.AppleDouble
.LSOverride
Icon
._*
.Spotlight-V100
.Trashes
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
使用する言語やプラットフォームごとにオススメのgitignoreを検索できるgitignore.ioが便利。
ホームディレクトリ(に ~/.gitignore
ってファイルを作れば、すべてのレポジトリで当該ファイルを無視してくれる。
.gitignoreの話をしたので、ついでに.gitconfigも。
CUIから追記するには…
$ git config --global user.name <username>
$ git config --global user.email <email>
~/.gitconfig
に直接書いてもOK。
[user]
name = Kouhei BABA
email = kouhei@szk-engineering.com
[color]
ui = true
[alias]
co = checkout
ci = commit
st = status
br = branch
graph = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
hist = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short
[core]
excludesfile = ~/.gitignore
名前とメールアドレスを設定しておかないと commit
できないので注意。
変更追跡するファイルを追加(= staging)したら、実際に変更点をまとめてindexに追加する。
$ git commit -m "<comment>"
<comment>
のところで変更内容を具体的に書いておく。
どんなタイミングでcommitするかは後述。
cf. http://qiita.com/ken_c_lo/items/4cb49f0fb74e8778804d
ローカルの変更をリモートに反映させる。
$ git push origin master
origin
と master
が何を意味するかは後述。
cloneしてないレポジトリの場合、そもそもリモートレポジトリがどこにあるか教えてあげないといけない。
$ git remote add <name> <url>
<name>
が前述の origin
に相当します。
1つのローカルレポジトリが複数のリモートレポジトリを見ることもできるので、ニックネームをつけていると考えればOK。
GitHubなら github
にするとか、自分にしか見えないところなのでわかりやすく自由に。
他の人が加えた変更点を自分のローカルに反映するとき。
$ git pull origin master
master
が何を意味するかは後述。
この時、conflict(衝突)することがあるけど、その原因や解決方法については後述。
git pull
git fetchとgit mergeを同時に行うコマンドです。
git-pull
: 他のリポジトリやローカルブランチから取得して統合します。
git-fetch
: 他のリポジトリからオブジェクトと参照をダウンロードします。
git-merge
: 2つ以上の開発履歴を結合します。
gitの機能として、本流とは分けて試したいときなどはbranchを切って、独自の開発路線を作っていくことができます。
レポジトリを作ると master
というbranchが必ずできるので、本流= master
という理解でOK。
$ git checkout -b <branchename>
-b
オプションを付けることで、 branchname
というbranchを作成しながら、 branchname
での作業を開始できます。
なので、既に作成してあるbranchに移る場合は -b
は不要。
branchを分けるとややこしくなると言えばややこしくなるので、ここでちょっと整理。
$ git checkout
とすると、今、自分がいるbranchが表示されるので適宜確認。
$ git branch
とすると、レポジトリにどんなbranchがあるか一覧できる。
基本的に、branchが違えば何をしてもOKなので、うまくいくかわかんない時や試してみたい時には積極的にbranchを切る。 その後、うまく行った場合には後述するmarge作業をして、本流に反映する。
branchを切った後や、または他の人の変更点と範囲が重なる変更をした場合、marge(統合)が発生する。たいていは自動で統合してくれるけど、conflict(衝突)すると、結構めんどう。
特に後者「他の人の変更点と範囲が重なる変更」での衝突はpushする前にこまめにpullするだけでかなり省けるのでこまめにpullする習慣をつけよう。
conflictした例を紹介する。
$ git merge hoge
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
何やらindex.htmlでうまくmergeができなかったらしい。
index.htmlを開いてみると、こんな風になっている場所があるはず。
<<<<<<< HEAD
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> hoge
HEADとhogeで違う記述をしている箇所があるので、どっちが正しいか判断して修正する。修正する際には記号の行も削除。
<div id="footer">
please contact us at support@github.com
</div>
修正後にadd→commitすればOK。
最初のうちはmerge手順がわからなかったり、どちらが正しいか判断がつかなかったりするのでレポジトリの管理者に相談しながら進めてOK。
Gitを使っていてちょっと面倒なのが、ファイル名の変更や削除。 OSのファイラからいじるとworking treeに残ったままになったりするので、Gitのコマンドから変更(移動)/削除するのがbetter。
$ git mv <src_filename> <dst_filename>
$ git mv <filename>
うっかりworking treeに残ったファイルをどうにかしたいときはcleanする。
$ git clean -f
"-f"で強制的にcleanしてしまうので、それが怖い場合には"-n"でcleanされるファイルを確認してから行うと良い。
差分を表示するときに使う。
たとえば、ファイルの差分を表示するときは…
$ git diff <filename>
よく使うのは、commitしてないworking treeとの差分。
$ git diff --cached
working treeの状態を表示する。
$ git status
commitのログを表示する。
$ git log
logより要約度の高いlog。
$ git shortlog
logのオプションで、ちょっと綺麗な履歴表示が可能。
$ git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
もちろん、いちいちこんなに長く打ってられないので、gitconfigにaliasを書いておくと吉。
簡単にcommitするための、"git add ."と"git commit -m <日付>"を同時に行うコマンド。 MacOSX + HomeBrew環境なら下記でインストールできる。
$ brew install --zsh-completion git-now
インストールが終わったら、git nowするだけ。コメントに日時と差分が纏まってcommitされる。
$ git now
$ git log
commit e3d45f97a5a1faf87a2fb3bf491dd5ea0f1644c9
Author: Shin'ichiro SUZUKI <shin@szk-engineering.com>
Date: Wed Aug 13 11:36:26 2014 -0700
[from now] 2014/08/13 11:36:26
diff --git a/gitconfig b/gitconfig
index cb6889a..24146ca 100644
--- a/gitconfig
+++ b/gitconfig
@@ -3,11 +3,16 @@
email = shin@szk-engineering.com
[alias]
graph = log --graph --date-order -C -M --pretty=format:\"<%h> %ad [%an] %Cgreen%d%Creset %s\" --all --date=short
- log = log --stat
+ sl = shortlog
+ sh = show
st = status
co = checkout
+ rbm = rebase master
+ gr = grep
+ dw = diff --color-words
[color]
ui = true
[core]
editor = vim
-
+[push]
+ default = tracking
簡単に commit
できる一方で、ソースを読まないと変更内容がわかりにくくなるので乱用注意。
ここまででGitの基本的なコマンドは習得したので、これらを実践的に組み合わせてみる。
git-flowという「こうやるとうまくいくよ」という手法がある。 そのまま適応させるかは別にして、知っておくと吉。
- masterに直接変更を加えない
- すべての変更は事前にbranchを切ってから、それをmargeする形でmasterに反映していく
- masterは完動する状態以外許さない
- masterはいつでも本番環境にdeployして良いようにしておく
- 各branchへのcommitもテストを通ったものしか許さない
- ただ変更しましたーって言うcommitはしない
- master
- 大元締め、常に配備可能なバグのないbranch、開発者は直接さわってはいけない
- develop
- 開発するためのbranch、ここからfeatureを切り分ける
- feature
- 直訳すれば"機能"、developからbranchして、ある一つの機能を実装するために使う
- release
- featureが何個かまとまって、release(公開)するためにドキュメントの整備などを行うbranch
- hotfix
- 発見された不具合を修正するために切るbranch、たいていはmasterから切り出す
- commitログがすっきりして変更履歴を追いやすい
- branchごとに担当者が分けやすくて管理しやすい
- branchごとに何をしなければいけないか明確化されてて作業しやすい
- masterはいつでも動くという安心感
- 変更履歴は追いやすいけど、進行中の作業は追いにくい
- branch切ったりmargeしたりする回数が増えて、正直めんどい
- テストを自動化しておかないと回せない
- 小規模な開発や実験的な開発で適応するといちいちcommitしにくくて困る
Git Flowは大げさすぎるので、GitHubを使ってGit Flowっぽいことをもうちょっと楽にやろう、っていうか、更にそれを改良して、szk-engineering流はこんな感じだよ。
- masterには直接変更を加えない(= Git Flowと一緒)
- 変更前にbranchを切って、完成(= テストが通る)したらPull Request(後述する)を送る
- Pull Requestを受けたら、mergeする前にコードレビューする
- masterは完動する状態を保つ(= Git Flowと一緒)
- masterはいつでも本番環境にdeployして良いようにしておく
- branch切ったらcommitは適当でOK。
- master
- 大元締め、常に配備可能なバグのないbranch、開発者は直接さわってはいけない(= Git Flowと一緒)
- feature
- 開発するためのbranch、1機能ずつ切り出す
- Git Flowとちがって、masterから切り出す(= developは作らない)
- hotfix
- 修正するためのbranch、1バグずつ切り出す
- masterから切り出す
developやreleaseを作らずに簡素化。
branchを作る時には必ず名前の先頭に0埋め3桁の数字を入力する。
e.g. 003_markdown_Notation_Error
- レポジトリをcloneする
- 開発する機能を決める(ex. submitボタンを付ける)
- わかりやすい名前でbranchを切る(ex. feat_make_submit_button)
- 機能なら"feat"、修正なら"hotfix"を付けて、アンダースコアでつないだ簡単な英文
- 開発する
- 開発が終わって、テストも通ることを確認する
- commitする
- pushする
- Pull Requestを送る
- Pull Requestを受け取った管理者はコードレビューしてmerge、問題なかったらbranchを削除
- 次の開発(or 修正)へ…
※ 2017/11/16追記: 最近の社内ではGitHubのIssues機能なども連携することが推奨されるようになりました。
GitHubの肝。とは言え、forkしないPull Requestは簡単。
GitHubのレポジトリの画面でbranchを切り替えて表示すると右上に"Pull Request"というボタンが出てくる。
Requestの相手(通常はレポジトリの管理者)と変更した内容を書いて送信。
GitHubが使えるようになったら、GitHubの周辺にも手を出してみよう。
CI(Continuous Integration; 継続的インテグレーション)を支援して、要するに、なるべく自動化して品質改善や納期短縮を効率よくやりましょうってサービス。 Publicなレポジトリなら、.travis.ymlというファイルを置くだけで使える。
自前で同じようなサービスを用意するならJenkinsが有名。
CIについては別途Lectureしましょう:)
読み方は「へろく」。RubyやらPythonやらをpushするだけで動かしてくれるPaaS。 小規模なら無料だし、たくさんあるAdd-Inが便利なので、まず動かしてみたいときに使う。
GitHub謹製の人工無能(?)。いや、かなり有能かも。
- 発言に含まれるURLのタイトルを表示
- TwitterのURLから発言内容を表示
- ミーティング時間の通知
- サーバの負荷が上がった場合に通知
- GitHubのリポジトリにpull requestが送られた場合に通知
- Jenkinsでのビルドの失敗時にエラーを通知
- デプロイの実行
間違いとかあったら教えてください。