Git

Gitコマンド これだけ覚えておけば大丈夫

バージョン管理のGitは非常に多機能でいろいろなことができますが、普段使うコマンドは限られています。
これらのコマンドを覚えておけば問題なく一通り開発できる、というGitコマンドのリストです。

基礎

そもそもGitとは?的なところは既知という前提で進めますが、Gitを使い始めた人が誤解しやすい点だけ下記に記載します。
Gitにはローカル、origin、リモートの3種のリポジトリがあり、それぞれ
ローカル:コマンドを叩いている端末に入っている、実際に作業を行っているところ
origin:コマンドを叩いている端末に入っている、リモートのコピー
リモート:作業者共通で使ういわゆる大元になる部分
originを意識しないのでGitがよくわからなくなる人が多いです。
Gitのコマンドは各種コマンドの実行時に毎回リモートを見るわけではなく、基本は通信せずこのoriginを見ていて特定のコマンドを叩いたときにのみ通信してリモートからoriginへコピーを行っています。
originは手元の端末のものなので厳密にいえばローカルですが、ローカルとリモートの間にあるものと理解するとわかりやすいでしょう。この記事内ではローカルというのはoriginを除いたもののことを指しています。
originは追跡ブランチと呼んだりすることもありますが追跡ブランチは人や文脈により解釈が違って紛らわしいので注意してください。

Git運用ルールの前提

変に一般化すると結局ごちゃごちゃするので下記の前提で運用しているものとして書いています。当然、所属組織のルールがあるならそれに従ってください。
・(ファイル変更の)履歴改変はしない
ミスと開発遅延の元、特にpush -f とかやっちゃうとバージョン管理の意味がない
ごちゃごちゃとコミットを一つにまとめるとかも無し、どうしてもならプロジェクト管理ツールと連携する
・本番環境はmasterブランチ
ブランチを切って開発を行い、masterブランチにmergeすることで開発を進めていく
・リモートとローカルのブランチ名はあわせる

初期化

初期化は外部サービスと絡んだりして書くと長くなるのでここでは記載しません。

新規ブランチを作成

ただブランチを作成するだけならgit branchですが、ブランチ作成だけして作業しないってことはないのでブランチ作成と同時に作成したブランチに切り替えます。

masterから作成

$ git checkout master
$ git pull
$ git checkout -b (new_branch)
$ git push -u origin (new_branch)

masterを最新の状態にした上でmasterから新規ブランチを作成します。
また、push -u をしておくことで今後引数無しでpull, pushができるようにしています。
pull, push時に毎回ブランチ名を指定すると間違えて別ブランチにあげたりしてしまいやすくなるのでそれを防ぐ意味もあります。

すでにリモートにあるブランチからローカルに作成

$ git fetch
$ git checkout -b (branch_name) origin/(branch_name)

e.g.) $ git checkout -b fix1234 origin/fix1234
fetchでリモートの情報をoriginに落としてから、originのブランチを元にローカルに作成しています。

コミット

git statusにてchanges to be committed:以下に表示されている緑文字で表示されているファイルについてcommitが適用されます。
changes not staged for commit: 以下に表示されている赤文字のものは変更されているけれどステージングされていない(commit対象にはなっていない)ものです。

確認 〜 ステージング

$ git status
$ git diff (file_path)
$ git add (file_path)

statusで変更したファイルを確認し、diffで変更点を確認、addでコミット対象に含めます。
変更点をすべて把握していて問題なければ

$ git add .

ですべて追加することもできます。当然、相対パス指定なのでディレクトリを移動していればそこのディレクトリ以下になります。

$ git rm (file_path)

ファイルを削除すると同時にステージング(git add)します。

$ git reset (file_path)

でコミット対象から外すことができます。(変更は維持されたままです。)

$ git checkout -- (file_path)

で、ファイルを変更前の状態に戻します。ステージングされている場合はステージングされたときの状態に戻します。

コミット

$ git status
$ git commit -m '(コミットメッセージ)'
$ git push

e.g.) $ git commit -m 'fix get item data API'
statusでコミット対象のファイルを確認してからメッセージをつけてコミットします。
コミットメッセージは対応していればマルチバイト文字も可能ですが、できれば使用しない方がいいでしょう。
コミットするときはpushもしておく癖をつけておくことでコンフリクトしにくくなります。

コミット名の修正

ファイル変更の履歴は後で追えなくなったりコンフリクトしてカオスになるので基本的に改変しない方がいいですが、今のコミットメッセージ間違えたというときには修正しましょう。

$ git commit --amend -m '(コミットメッセージ)'

こちらで直前のコミットメッセージが編集できます。

ブランチの移動

移動

$ git checkout (branch_name)

現在のブランチを確認

$ git branch

 本番環境(masterブランチ)へマージ

$ git checkout master
$ git pull
$ git merge --no-ff (branch_name)
$ git push

fast fowardで履歴が残らないことを防止するために明示的に--no-ffをつけています。

ブランチの削除

作業が終わったローカルブランチは削除しておくと見通しがよくなります。
間違ってmergeしていないブランチを消さないように注意しましょう

$ git checkout master
$ git branch -d (branch_name)

現在いるブランチは削除できないのでmasterに移動しています。本番環境へのマージ後にやるようにしておくとスムーズです。
警告がでて-Dにしろと言われることもありますが、その場合はマージしていないなどの可能性があります。
よく確認して、問題なければ $ git branch -D (branch_name) として強制ブランチ削除を行いましょう。

$ git push origin :(branch_name)

e.g.) $ git push origin :fix1234
リモートからのブランチ削除です。リモートからも削除が必要かは方針に従いましょう。

切り戻し

$ git log

で打ち消したいコミットのコミットIDをコピーして

$ git revert (コミットID)

とすることで打ち消しをコミットできます。
マージをもどす場合は

$ git revert -m 1 (コミットID)

でできますが、1を指定で元のブランチを残します。2を指定するとマージした側を残してしまうので注意してください。
どちらの場合も、再度作業をする際はrevertのコミットをrevertして作業再開します。
もう作業ブランチでやり直す場合は一度作業ブランチに戻り、

$ git merge master

これでmasterと同じ、打ち消した後の状態になるのでrevertのコミットをrevertで打ち消します。(二重打ち消しで変更分がまた出てくる)

$ git revert (revertのコミットID)

これをしないとマージしてもrevert前の変更はすべて消えたままになります。mergeはソースを統合するのではなくコミットを統合するので、revertで消したら変更は削除を打ち消すrevert(等)でまた書く必要があるのです。

未コミット分を戻す

なんか動かなくなった、やっぱここいらなかった、ブランチ切り替えれないなど、とりあえずコミットしてあるところまでもどしたいときに。
こちらは作業がなかったことになるので、作業内容を保持したまま作業分を一旦リセットしたいときには下記の作業中断を参照。

$ git reset --hard

主にブランチを切り替えられなかったときなど、特定のブランチの状態に強制的にあわせるには下記を使います。

$ git reset --hard origin/(branch_name)

作業中断

作業分を一旦おいておきます。あまり使いませんが、別ブランチの作業が入ったけれど今の作業分が中途半端すぎてコミットはしたくないときなどに使います。後で戻せるgit reset --hardという感覚です。

$ git stash

$ git stash list
$ git stash pop
$ git stash drop

別ブランチから特定のファイルをとってくる

先にここだけ反映したかった、別ブランチで作業したものが必要になったなどのときに使います。ディレクトリを指定すればディレクトリ以下をまるまるとってきます。

$ git checkout (branch_name) (file_path)

コンフリクトしたら

pullやmerge、stash pop などをしたときにコンフリクトが起きることがあります。
$ git status でCONFLICTしているファイルを確認、コンフリクトを解消してgit addします。
すべてのコンフリクトを解消したら$ git commit をして確定しましょう。

編集履歴確認

$ git log

e.g.) $ git log example/example.php
誰がいつなんのコミットをしたか見ることができます。引数にブランチやファイル名を指定することもでき、特にファイル名を指定した場合はそのファイルを編集したコミットの一覧が出るので便利です。引数を指定しない場合は現在のブランチのコミットを新しいものから表示します。

$ git log -p

e.g.) $ git log -p example/example.php | grep --color -e 'commit' -e 'Author' -e 'hogehoge'
-pをつけると変更点も出ます。基本的な使い方は同じです。例のようにgrepを使うことで対象のファイルのhogehogeが含まれている行の変更をしたコミットとコミット者を洗い出せたりもします。

最後に...

設定などはともかく、基本的にgit操作はこれらのコマンドだけで完結するかと思います。
他の人が変なコマンド打ってトラブったときなどにはこれ以外のコマンドも使います。
pull,push感としては基本的に、作業開始時(始業時やブランチ切替時)にはpull、作業終了時(就業時やブランチ切り替え前)にはcommitしてpushします。
また、ブランチを切って長期間経過していたりして本番と乖離してそうなら適宜masterブランチを作業ブランチにmergeして合わせます。
masterへのmerge(=作業ブランチの分離)の粒度ですが、すぐ終わるなら新規ページのバックエンドとフロントと全て一括でやってもいいですし、時間がかかりそうなプロジェクトならAPI一つ作成などするたびに本番にmerge、としておけばコンフリクトが少なくなります。
コンフリクトすると面倒なのでコンフリクトしにくい程度にこまめにpull,push,mergeを行っておくという感覚です。
もし何かありましたらコメントいただけると幸いです。

-Git