この記事はみす裏 Advent Calenderの5日目です。
でもこのブログについては深く考えてはいけないよ
焼酎の話とかでも離すかと思ったけど先日酒池肉林に行った折に二日酔いでやられたので、今日のところはgitについて話します。
なんでgitつかってるの
最近は相変わらずコミケに苦しんだり研究に進捗が出ないことに泣いたりしつつ、
コトノネドライブの画面なんかを頑張って作っているのですが。
最近自分でコードも書いたりしてたので自由に更新できたらなぁ…と思い、
うっかり「yukiさんgithubの使い方教えて」と言ってしまいまして。
その結果現在は元気に闇に飲まれよ!と創造の神器に鞭打たれて元気です。
で、苦しみつつgithub。使ってますが、ようやく自分の作業を反映できるように鳴りましたので、過去の自分がもやもやしていた部分をここらでまとめてみました。
まあ初心者的ですよ?基本的にはこっちを見たほうが早いでしょうし、間違いも多々ある気がしますが、まあひつまぶしにお付き合い下さいよ。
なぜなにgit
...とまずは前提として自分が分かんなかった事をいくつか
① gitHubはgitという進捗管理システムの1つにすぎない
そんなところからかよ!そんな所からだった。
gitと調べるとlabとかhubとか色々出てきまして謎だったんですが、要はバージョン管理システムの一つがgitというのですね。「お絵かきソフト」「表計算ソフト」的なレベルね。
<追記:>システム管理ツールそのものをgitと呼ぶというのは語弊があったかも。svnとかmercurialとかノートにかくのでも色々進捗管理はできるけど、ソレを便利に扱いましょうねっていう方法の一つがgitですね
バックアップを取りたい時、普通は「ファイル自体をコピー/圧縮する」でしょ?でもgitは「セーブポイントごとに変更された事柄だけ記録する」わけ。「このtxtの5行目が変わって6行目が増えた」「この.pngが消えた」みたいにね。
これでコピペファイルを量産すること無く過去の作業履歴を保持できるわけよ。すげぇ。このセーブポイントを「commit」といのか。なるほどね
②gitはコマンドラインから操作できる
これもそんなとこからかよ!レベル。
gitを操作する方法は、web、git bashのようなCUI、github for desktopやsourceTreeのようなGUI。bashで操作した場合、リポジトリのフォルダに移動すると勝手にリポジトリを認識してくれる。
最初はGUIで操作してたんだが、こいつ衝突とかがあると直ぐエラー出すので、CUIでの操作も覚えたほうが自由度が多くてストレスたまらないと思う。いやほんと
③gitは指定したファイル中の変更を検知する
リポジトリってのは1つの作業フォルダ全体。たとえばコトノネのリポジトリを登録すると「kotononeフォルダを監視するよ!」となる。
この中で何かファイルを追加・削除・変更すると、gitさんはそれを検知して「ここ前と変わってるゾ」と教えてくれるわけだね。頭いいね
変更の例
gitさんが教えてくれた変更に対して「じゃあこのファイルの変更を保存(=変更確定)するよ」ということをcommitというわけ。コミットしないと保存は確定されない
逆に変更をなかったコトにすることをdiscardという。これも使ったりする
④gitで自分が見ている現在地が「HEAD」
gitのリポジトリは、基本このcommitを繰り返し、電車の路線みたいに先へ先へと進んでいくのだな。
…それぞれの白丸が「機能Aを追加した駅」ー「機能Aのバグを取った駅」ー「素材B.jpgを足した駅」ー「機能Cを作った駅(最新)」 って感じ。右端の黒円は「まだcommitしてない変更」部分
git自身は路線を自由に動ける電車のようなもので、自分はその電車に乗っているってイメージだよ。水色のところだね。
この電車がHEAD。git使ってるとでてくるけど、君がいま居る場所がHEADだよ。
HDDの読み取り部もヘッダって言うでしょ。
HEADが移動すると、手元のファイルの中身はそれにへんこうされるよ。
サイレントで。エディタ開きっぱのとき注意。
git説明サイトなどで「HEADが移動して…」などと言われたら、「乗ってる電車(いま参照しているデータ)が動いたんだな」となんとなく思えばいいよ。
⑤originってなんだよ
gitって全部オンラインで完結するもんだと思っていたのだが、少なくてもgitHubに関してはそうじゃなかった。
ローカルのファイル / ローカルブランチの各コミット履歴
⇅
リモートのファイル / リモートブランチの各コミット履歴
こうなってる。
ローカルでブランチ作成/コミットを作ってもリモートに上げる(push)必要があり、
リモートのコミットはローカルに取り寄せて更新をかける必要があるわけ。
リモートが関わるとき、gitのコマンドには originという引数がつく。素直にremoteとかにしてくれればいいんだけど、リモートの内容が本筋ということらしい。originの意味が謎だったので、コレ知った時スッキリした。お前がかい
変更をマスターに取り込むまでの流れ
これが本編。
人によって環境違うから、リポジトリ管理者に使い方聞いたほうが良い。
コトノネ譜面チームはこれみて譜面足そう
1. ブランチを作る
いきなりmasterブランチにコミットを足すのは危ないため、作業用のブランチを作る
git branch akisamo
これでmasterから分岐した、akisamoって名前のブランチがローカルに出来る。
2.実際に作業する
ここは頑張るしかない。がんばれ
コトノネ譜面でいえば、譜面ファイルをassetに追加して、譜面名をソースコードに入れるとかだろう
3.作業内容を保存(commit)する
git commit -m "murakumo_add"
最後の引数はコミットの名前。git for Desktopで見たほうが変更ファイルが一覧されるのでわかりやすいかもしれない。変更を保存したいものだけ選択して、commit名を入れてセーブする
4.最新版の内容を取り込む準備をする
さて、ある程度akisamoブランチにcommitをして、ではmasterブランチにいざ!この変更を反映してもらいたい。
でも、masterには他の人も別の機能を加えている(コミットをしている)。akisamoブランチにはその情報がない。
akisamoブランチの最新版に、masterブランチの最新の内容を反映させないと、他の人の追加したデータが消えてしまうかも…!
それを対処します
※未コミットのファイルがない状態で
git checkout master
git pull origin master
これでローカルのmasterブランチが最新版になる
git checkout akisamo
これでさっきまで作業してた自分のブランチの先頭にHEADが移動する
git rebase master
これが難しい。
今いるakisamoブランチってのは、例えば数日前のとあるmasterコミットから分岐しているわけだ。
これを「数日前じゃなくて今!最新のmasterコミットから分岐して作業してたらどうなっていたか?」という観点で自動的に変更していってくれる。
mergeとやってることは結果的に同じだけど、合成中のごちゃごちゃした状況を作業用のブランチ上で行えるのは、個人的にもログ管理的にもスッキリしてていい。
ここでもし衝突が起こったら、
git status
などでどこが衝突しているか確認し、解消されたら
git add 衝突してたファイル名
git rebase continue
とかして変更を完了させる。
無事rebaseが終わった時点で、手元のakisamoブランチは、masterブランチの最新版の内容を反映させた状態になっている。コイツが問題なく動けばすぐさまmasterブランチにコミットできるわけだ。しよう。
git push (--force) origin akisamo
akisamoブランチをリモートのakisamoブランチに(強制的に)アップロードする
あとはプルリクエストを遅ればok。怒涛のレビューを待とう
まとめ
ローカルでブランチを作って作業、ローカルでコミットしてから、rebaseして衝突を修正することで、リモートのマスターの最新版の内容を反映させる。あとはリモートにpush、プルリクをおくってリモートのマスターに取り込んでもらう
…こんなの実際に何回かやらないとわからんだろうが、2ヶ月やってみて自分の中ではこういう形で納得した。各自でこういう感じで納得したら、まとめてみると良いですよ。
困ったときにつかったコマンド
git status
とりあえず使う。変更されたファイル、衝突しているファイルなどがわかる
git branch -a
ブランチ情報を知る。-a とつけるとリモートのブランチも見えるぞ
git rebase --abort
リベースを取り消す。「やべぇコンフリでごちゃになった」時使う
git log --graph
コミット履歴を見る。 graphといれると路線図ががんばって可視化される。エディタちゃん頑張ってるぞ
git reset --hard /--soft HEAD^
多用するべきではないが私はよく使ってしまう神コマンド。
「ヘッダを引数のものに強制移動する」というもの。
コミットをやり直したいときは
git reset --soft HEAD^
でHEADが1つ戻る(コミットしたことでHEADが1回移動したから)
--softは「ファイルを上書きしない」。--hardにすると前回のコミット内容で完全上書きされ、変更ぶんのファイルも消えてしまう。
3日前のあのコミットに戻りたい時は
git reset --hard あのコミットのID
でファイルの中身ごと復元する。
御託は良いからmasterの最新版を取得したいときは
git origin --hard origin/master
あと、操作履歴を見るようにHEADの移動履歴を一覧する
git reflog
なんてのもある。これで「変な操作しはじめた14つ前のHEADに戻る!」なんて荒業もある。
git reset --hard HEAD{14}
このへんは多用するべきではない(履歴ごと消すから)けど、わりとこうやってなんとかなるから、恐れずにgitをいじってみましょう。よろしくね。CUI使おうね。gitなんとかとかポチポチ打つの楽しいからね