GitHubでチーム開発的なやつの備忘録
免責事項: Gitなんもわからん.チーム内規約がある場合はそっちに従おうな.
最初にやること
gitの初期設定メルアドとかアカウントとか登録する.sshの設定もしよう!
code:console
$ git config --global user.name "hoge"
$ git config --global user.email hoge@example.com
$ git config --global core.editor 'vim -c "set fenc=utf-8"'
$ git config --global color.diff auto
$ git config --global color.status auto
$ git config --global color.branch auto
$ git config --global push.default simple
$ git config --global core.quotepath false
$ git config --global core.autoCRLF input
SSH鍵の生成と登録
ssh鍵の生成.
code:console
$ ssh-keygen -t ed25519 -P パスフレーズ -f github_ed.pem 公開鍵(上の例ではgithub_ed.pem.pubが生成されている)はGitHubとかに登録しておく.
xsel をインストールしていれば,以下のコマンドで公開鍵の内容をクリップボードにコピーできる.
code:console
$ cat github_ed.pem.pub | xsel -bi
登録した公開鍵は https://github.com/user.keysとかで見れるので便利.(新しいサーバーの設定とかで必殺curl https://github.com/user.keys >> ~/.ssh/authorized_keys ができる.)
sshの設定をする.
code: .ssh/config
Host github
HostName github.com
User git
IdentityFile ~/.ssh/github_ed.pem
公開鍵と間違えて秘密鍵を公開して後悔しないようにしような!
最後にPermissionの設定をする.
code: console
$ chmod 700 .ssh
$ chmod 600 .ssh/*
ssh -T githubでちゃんと接続できればオッケー.
GPG鍵の生成と登録
いろいろやってGPGのsubkeyを作り,公開鍵をGitHubなどに登録する.(c.f. GPG鍵を作る) 自動でcommit,,tagに署名するようにする(merge commitは明示的に指定してやらないと署名されない).
code: console
$ git config --global user.signingkey GPG鍵のID $ git config --global commit.gpgsign true
$ git config --global tag.gpgsign true
GitHubなどに登録しているメアドと証明書のメアドが揃ってないと検証に失敗するので注意.
プロジェクトで一度だけやるかもしれないし二回やるかもしれないこと
元リポジトリをForkする(必ずしもやるわけではない.)
Cloneする
code:console
$ git clone git@github.com/Hoge/fuga.git
upstreamを設定する(Forkした時のみ)
code:console
$ git remote add upstream git@github.com/Bar/fuga.git
各Issueごとにやること
Milestoneを作成する
一つの開発サイクルごとに作成
Issueに紐付ける
Issueが期限過ぎた場合は新しいMilestoneつくって貼り直すのがベター
Issueつくる
追加機能,バグは必ずIssueで管理.なんか実装する前にちゃんと作ろう!
ないと後からなんもわからなくなる
必ずMilestone,Assignees(実装担当)を設定すること.
Labelをつける追加機能はenhancement,バグはbug,作業中ならin progress
Issueの優先度もLabelで管理しよう
topic branchをつくる.名前は<担当者>/<やること or 機能名>って感じに
人が多い場合は<issue番号>/<やること or 機能名> もよき
code:console
$ git checkout master
$ git pull upstream master
$ git checkout -b Hoge/fuga_bug_fix
空のcommitを作ってpushする
commit messageは[WIP] Issue名 (Issue番号)
今ではDraft PRがあるので,それでPRを作るほうがベター
code:console
$ git commit --allow-empty -m "WIP fuga_bug_fix (#1)" $ git push origin Hoge/fuga_bug_fix
タイトルに[WIP]をつけてPRを送る
PRは1つのIssueの作業を分割して,小さい粒度にする
1つのIssueに複数のPRはベストな状態
作業中に他にやりたいことできたら別にPRにする
PRの大きさはsquashしても違和感ない程度が目安
場合によっては変更が巨大になってしまう(テストファイルの一括変更など)が,意味的に巨大にならなければ許せる
PRにはIssue番号を,関連するIssueにはPR番号を入れておこう!
PRのコメントには目的,実装の概要,レビューして欲しいところ,不安に思っていること,保留してること
,関係するPRとIssueを書いておこう
レビュアーをAssignすることで作業開始と進捗をレビュアーが知ることができる
PRやIssueで随時相談しながら実装していこう!
相談場所はGitHub上にすることで,コードの変更意図が追える
Issueと同じMilestoneとLabelをPRにもつけておこう!
そして,作業へ……
随時commitとpushを行っていく
細かい粒度でcommitを行う
粒度がでかくなりそうだなと思ったらcommitの前にgit add -pでステージングを段階的にする
Issueで書いた本筋に関係ないことにはタッチしないようにしよう
バグを見つけたとかこのコードはこう書いたほうがいいのになとか思ったことは全部TODOとしてコメントに加えるくらいにしておく
試行錯誤の課程などはcommitに含まないこと
含んでしまったらあとでcommitを消しておく
commit messageは具体性と人間的意味を考える
基本的には一行目に"Prefix 追加内容 (Issue番号)"として,2行目を空行,3行目を具体的な内容にする
具体性
「Fix bugs」,「Add new class」はだめ
何を変更したかはdiffで追えるが,なぜその変更をしたかはわからない
「ヘッダーナビゲーションのボタンタップが正しく反応するようjQueryのセレクタ名を修正」という感じにする
5W1Hを抑える
人間的意味
「OLD_CONST1, OLD_CONST2を削除」,「MemberModelにsuccessフィールドを追加」はだめ
「ver2.0で廃止した登録関連の古い定数を削除」,「API取得が正常に完了したかを保持できるようMemberModelに新規のフィールドを追加」などが良い
なぜそのような変更をしたのか,実装をしたのかの意図を明確にする
PrefixはFix, Update, Remove, Rename, Addが基本
CIが必ず失敗することがわかっている場合や,CIを特に回す必要がない場合(Readmeの内容のみ変更)などは,ciskipなどをつけて余計なCIが回らないようにする
計算リソースは有限.大事に使おう.
pushする
git pull --rebaseはmasterのcommitのあとにtopic branchのcommitを適用していくので,PRをマージしたあとにmasterのコミットのハッシュが変わり人が死ぬということがないので安全
つまりpush時にforce pushがいらない
なお,一回rebaseしてしまうったあとに変更を加えて再度rebaseするとforce pushが必要になってしまう
そのような変更が巨大なブランチは作るなということだが,無茶いうなという場合はmergeで対応すべし
git merge -S [マージ元のブランチ]で署名付きのマージができる
code:console
$ git pull --rebase upstream master
$ git push origin Hoge/fuga_bug_fix
コンフリクトしたんだが……
git pull --rebaseがコンフリクトすると一旦中断されるので,ターミナルに表示されるboth modifiedで指摘されるファイルを修正して,git addし,git rebase --continueする
修正した結果無をコミットすることになってしまった場合(addしてcontinueしてもNo Changesとか言われてしまうやつ),git rebase --skipで飛ばす.
マージコミットが作られないのでlogがきれいなままだよ!
チームでコンセンサスとれてるのならmergeでもいい
PRの作業が終わった!
PRのWIPを外してレビュアーにメンションを送る
レビュー要請はこまめに出してもいい
というか全部実装してからPR投げると場合によっては変更箇所が多すぎてレビュアーが死ぬ
レビュアーがGithubのCodeReview機能でコードにいろいろコメントを付けてくれるぞ!!!
File chengedタブで行う
各行で+マークが出るのでそれでコメントつけて,Review Chengesボタンで全体のコメントを書いてRequest ChangesにしてSubmit Reviewをしよう!
問題ないからこれでmergeでいいでしょってときはApproveするといいぞ!
何人ApproveしたらPRとか決めておこう!
レビュアーにボロクソ言われて泣きながらコードを直す
新しくcommitをつくるとレビュアーが混乱するので,既存のコミットを修正する
修正したあとのcommitはgit commit --fixupで修正したい既存のコミットを指定しておこなう
pushして再度レビュアーに見てもらう
全部レビューが完了してマージできる状態になったらgit rebase -iをおこなう
そしてforce push.変更箇所のcommitのハッシュが変わっているのでforce pushしないといけない
code:console
$ git pull --rebase Hoge/fuga_bug_fix
$ git -c core.editor=true rebase -i --autosquash $(git merge-base Hoge/fuga_bug_fix @)
$ git push --force-with-lease origin Hoge/fuga_bug_fix
マージする.
squash mergeだとmasterのcommit logが汚れないので良き
PRの粒度が適切であれば,squashされたcommitのdiffも大きくなく,かつ意味が通るものとなっているはず
関連するIssueに関する最後のPRであれば,PRのコメントにclose <Issue番号>とか書くことでIssueを閉じれる
delete branchボタンでブランチを消そう
作業中に修正したくなった部分やまだタスクが残ってますか?よし,新しいPRを作ろう!
マージしたら後始末
ローカルのブランチとリモートのブランチを消す
code: console
$ git branch --delete Hoge/fuga_bug_fix
$ git push --delete origin Hoge/fuga_bug_fix
ブランチの切り方
git flowに従っとけばいいみたいなところある.ない?
逆引き
タグをつける
code:console
-s は署名.
タグをpushする
当然タグもpushせねばならない.
code: console
ステージング前の変更を取り消したい時
code: console
git checkout . で全部取り消せる.git restore もあるがまだ実験段階なので,お好みで.
ステージングを取り消したい時
code: console
コミットコメントを書き直したい場合
code:console
$ git commit --amend
pushしてしまってる場合は,force pushしないとならない(コミットハッシュが変わるため).
コミットを消したい時
code:console
消したいコミットの行を消して終了.
Gitの操作を取り消したい時
code: console
$ git reflog
ハッシュを確認
code:console
^HEADとか使うときはzshの場合^をエスケープする必要がある.
ロールバックしたい場合
ローカルリポジトリのロールバック
code:console
リモートリポジトリのロールバック
code: console
リモートリポジトリのロールバック(マージ済みの場合)
pushしたブランリがマージされちゃった場合.
code:console
リモートブランチをGitHub側で消したのになんかローカルに残ってる時
以下のコマンドで更新できる.
code: console
$ git remote update -p
間違えてmasterにコミットしてしまった場合
まずブランチを本来切るべきところだった場所からブランチを切る.
code:console
コミットハッシュの部分とかは origin/master とかでもいい.
次に,間違ってコミットしてしまったコミットのハッシュを探してcherry-pickでコピー
code: console
最後に間違えてコミットしてしまったブランチから件のコミットを消して終わり.
code: console
自分の作業ログを取りたい
以下を.gitconfigファイルに追記
code:console
logfile = "!f () {\
git log --oneline --branches --reverse --date=short\
--author=\"$(git config user.name)\"\
--pretty=format:\"%ad %h: %s\"\ --since=\"$1\"\
~/log.txt;\
};f"
以下のコマンドである日から今日までのログがhome以下にlog.txtとして出力される.
code:console
$ git logfile 2018-12-1
お気持ち
基本は,他人の担当部分を変えるな,不要なlogは入れるな,変更はでかくするな
チーム開発なのでさもありなん
レビュアーのことを考える
きれいでレビュアーの負担が少ないPRが作れるかは,事前の検証,設計,作業の適切な分割にかかっている感じがする
これらはIssueレベルで議論
人類にないものオンパレードで笑ってしまう
署名はチーム全員でやっといたほうが良さげ
コードの信頼性の検証ができるので.
CI/CD時にコードの検証ステップを挟むことができる
セキュリティ的にはMUST
どこまできっちりやるかはチームの規模や成熟度次第
スタートアップ初期のようなレビューをしっかりやらない(あるいはやれない)場合はPRの粒度や過去のコミットの編集などはしなくてもよい気もする
その他はMUSTだが
正直gitとか適当に使えばええやんみたいなお気持ちがあるけど,ココらへんに書いたことを徹底しないとレビュアーが発狂しがちというのもあり,gitめんどくさい難しいという気持ちでいっぱいです.
参考にすると良いやつ