個々のコマンドの説明とか、Gitの記事はたくさんあるので、細かい話はしないです。僕がいつも説明するときに言っていることをまとめて、説明時間を短縮する目的の記事です。
(今更Git記事書くなよとかあると思いますが、そこはご容赦ください。)
対象者
ある程度、SVNなどをやっている人向けなので、説明が足らないところや省かれているところがあります。そこは適宜ググッて頂きたいです。(キーワードでググれば大丈夫かと)
僕のGit歴
説明するとか言いながら、Git初心者野郎だった。とかだと嫌だと思うので経歴です。
- Git歴2年以上
- Git移行委員会とかやったことある
- BFGとか使って、大きなバイナリファイル削除したりした
- SVNからGit移行とかもやったことある
GitとGithubは違うもの
プルリクエストの機能はGitには無く、Githubの機能です。なので、gitコマンドではなく、hubコマンドを使わないとプルリクエストの作成などは出来ません。
Gitの概念
Gitはバージョン管理ではなく、変更管理なんだという記事があります。そう考えると後々の理解が若干楽になると思います。
Gitの構成
この図には、後述するローカルのrefs領域が書いてないですが、他は書いてあるので引用です。
サーバーにあるもの
- サーバーのGit領域(upstreamリポジトリ)
ローカルにcloneした時に出来るもの
- サーバーのGitファイルを置く場所(refs領域)
- 自分のGitファイルが置いてある場所(ローカルリポジトリ)
- index領域(index)(stagingとも呼ばれたり)
- ワークスペース(workspace)(見えているファイルはこれ)
- STASH領域(僕はstash使ってないので、説明しないです。)
各コマンドがどこを更新するか?は、次から説明します。とりあえず、各領域があり用途により分かれているということを、覚えてほしいです。
git initは使用しなくてもおk
他のサイトだと、git initすると書いてありますが、僕は使っていないです。Githubとかで作業するなら、cloneしかしないスタイルでも事足りると思います。Githubの画面からリポジトリを作成して、READMEと言語の選択してリポジトリを作成します。これをやると、副作用で.gitignoreとかもついてくるのでお得です。
(最初はスキップ出来るところはしたほうが良いというスタンスが良いと思います。)
git cloneの種類
httpsとsshの2パターンあります。また、ローカルにあるGitクライアントが古い場合、httpsでクローンが出来なかったりするので注意です。その場合、バージョンを上げてください。
https
git clone https://github.com/daijinload/hoge.git
こちらでcloneすると、pushするときに、IDとパスワードを聞かれます。
(IDEを使用している場合、IDとパスワードは保存出来ると思います。)
ssh
git clone git@github.com:daijinload/hoge.git
こっちはパスワードとか聞かれないので良いのですが、sshkeyを作ったり、自分のgithubの設定に公開キーを置く必要があるので、コマンドでガンガンコミットする人以外は、シンプルに使いたいのであれば、パスしたほうが良いかと。
さらに、keyが1個しか無いなら、↑で良いのですが、複数設定したい場合、~/.ssh/configに設定書いて、
git clone git@ほげほげ:daijinload/hoge.git
という感じで、分岐名称を指定する必要があります。
GitHubの複数アカウントを使い分けるならSSHよりhttpsの方がいいんじゃね?という話
ただし、何かしらノンパスで作業する必要のある人は、設定せねばならないと思います。
(jenkinsとかのCI環境で、Gitで複雑なことやったりする場合とか)
statusとlog
git status
git log
状況確認コマンドです。hash値を調べたりするのにも良いので、使っていってください。
gitでサーバに変更を送る(push)
git clone hoge.git
cd hoge
touch aaa.txt #(ファイル作成)(ワーキングディレクトリを更新)
git add --all #(index領域を更新)
git commit -m 'add aaa.txt' #(ローカルリポジトリを更新)
git push origin master #(ローカルリポジトリの変更分をサーバに送る)
IDEを使えば、addとcommitをセットで行えるので、僕はそうしています。手でやる時も、--allを使うなど可能な限り楽をします。
git commit -am 'update'
このコマンドなら、addとcommit同時にできるのですが、新規ファイルは出来ないため使ってません。
gitでサーバーの差分を取ってくる
git fetch origin #(ローカルのサーバーのGitファイルが置く場所を更新(refs領域))
git rebase origin/master
git pullは使いません。pullだとfetch + mergeとなるので、fast-forward出来ない場合、意図せずコミットが作成されるからです。たまにプルリクエストにmasterにある変更がマージコミットとして差分として出たりするのですが、それはこれが原因です。
ここはつまづきポイントだと思います。
git pull --rebase
使うとしても、基本は、こんな感じで使ってほしいです。
ともかくmasterに戻したい
git reset --hard origin/master
サーバー側が進んでいる場合、fetchしてからやると良いです。
豆知識 origin/masterの所を、コミットハッシュ指定出来るので特定コミットに戻りたい時などどうぞ。
origin/masterとorigin masterの違い
- origin/masterとスラッシュが付く場合、ローカルのrefs領域を指します。
- origin masterとスペースが付く場合、サーバーを指します。
ここもつまづきポイント。pushする場合、ローカルに向けないと思うのでスペースと覚えると間違いないと思います。
gitでmasterを最新にしてからブランチを切る
git checkout master
git fetch origin
git rebase origin/maseter
git checkout -b feature/hoge
単純にcheckoutしてブランチを切る場合、ローカルリポジトリのmasterを最新にしておかないと古いやつで切ることになって、コンフリクトの危険性がマシます。。。
git rebaseは2種類ある
- git rebaseは、マージっぽいやつ
- git rebase -iは、過去編集モード(コミットをまとめたり出来る)
僕のスタイルだとブランチ切った後は、小さい単位で、pushしまくります。コメントが適当でも、最後にコミットをまとめれば、無かったことにできます。また、OSSでプルリクエストを送る場合、コミットを綺麗にしないとダメなんだからね!!と言われる場所もあるので、git rebase -iはマスターしたほうが良いです。
git rebase -i 34ab39c4
また、上記のようにコミットハッシュを指定すれば、HEAD^3とか覚えなくて済むのでおすすめです。コミットをまとめることを、squashしてね。とか言ったりします。
git戦略
git-flowとgithub-flowが良く知られています。いままで現場を見てきた感じ、そのまま採用するチームもあれば、足して2で割ったような戦略にしているチームもありました。SVNを使っていたチームなら、SVN時代と同じ感じでやるのが分かりやすいのでは?と、個人的には思います。僕の居たチームではタグコミットが頻繁にあったので、stable/hogeとかでブランチを切ることをタグ切り扱いにして、それをリリースしたり、stable/hogeに対してcommitをpushしたりしてました(gitのtagを使ってない)。シンプルで誰でも理解できる戦略であれば、なんでも良い気がします。
stashを使わない理由
stashは、手元に編集中のファイルがある状態で、ブランチを切り替える時に便利な機能です。ですが、ローカルのPCに長い間ファイルを置いておくと、PCが突然死した時に作業分が失われるというリスクが高くなります。Gitは分散リポジトリなので、ローカルでコミット出来て便利と、ずっとpushしないで作業したりするのは危険だと思います。なので、僕は突然死の被害を抑えるために、ブランチを切って、途中でもファイルをサーバーに送っていくスタイルを取っています。そうしていたら、stashを使わない開発スタイルになっていた感じです。
バイナリファイルは苦手
性能観点からストレージ制限
1Gbyteを超えた当たりでGitが重くなるようです。
僕の前に居た会社では、GitHub Enterpriseを使用していたのですが、1Gbyteを超えた当たりで、管理チームから小さくしろと勧告が来ました。その時に、BFGを使用して要らないバイナリファイルを削除したりしました。
(git filter-branchコマンドもあるのですが、遅かったのでBFG使いました。)
最近では、大容量ファイルもGitで管理。 Git LFSの使い方も出てきているので、そんなことをしなくても良いのかなぁと思ったりするのですが、使用している方、経験談を頂けるとうれしいです。
まとめ
ざっくりと以上となります。説明するときにこれを読んでもらって、フィードバックを得て、さらに改良していこうと思います。また、変なところや、分からないところがありましたら、コメントおねがいしますm(_ _)m