Gitの知識がほとんどなかったiOSエンジニアがいままで現場で使ったコマンドまとめ
はじめに
現在現場は 9 ヶ月目で Git は 8 か月間実務+個人開発で使ってきました。
研修中は,SourceTree 使っていたので,できる気になっていたけどそんなことなかった。研修中に実践的にやっておけばよかったと思った。新入社員の方にも聞いて使えない方は使えないようだったので書いてみました。
はじめの現場で結構教えてもらって使えるようになったのでよく使うの,知っておくといいかも的なの書いていきます。個人で使う分のも含まれてるかもしれません。
場合によって適宜追加修正していきます。
スクショも貼ればいいんだろうけど長くなりそうなので実際に打ってみてください。
☆ は経験上で使ったなーって頻度です。
init 系 ☆
基本的にこれを打つのは個人開発がほとんどかと。GitHub や GitLab の場合はリポジトリ作った段階ですでにプロジェクトがある場合はこのコマンド打て!ない場合は作れってでるのでそれに従うといい。
remote ☆
Git管理しているリモートリポジトリとか調べるとき下記コマンド。これ打つと origin の意味がわかるようになった。
$ git remote -v
origin git@github.com:MilanistaDev/tests.git (fetch)
origin git@github.com:MilanistaDev/tests.git (push)
この origin とかが下記のときの push 先。
$ git push origin feature/hoge/hoge
必ず origin でなければならないわけでなく,複数のリモートリポジトリを登録できる。個人だとほぼないだろうけど,バックアップ的な使い方はできる。
git remote add 名前 リポジトリ(.git or url)
$ git remote add gitlab git@gitlab.com:Milanista224/tests.git
出力例は下記。管理しているリモートリポジトリが増える。
$ git remote -v
gitlab git@gitlab.com:Milanista224/tests.git (fetch)
gitlab git@gitlab.com:Milanista224/tests.git (push)
origin git@github.com:MilanistaDev/tests.git (fetch)
origin git@github.com:MilanistaDev/tests.git (push)
push するときなどは origin のところを変えるだけ。
$ git push gitlab feature/hoge/hoge
逆に消す場合は,下記。
git remote rm 名前
$ git remote rm gitlab
$ git remote -v
origin git@github.com:MilanistaDev/tests.git (fetch)
origin git@github.com:MilanistaDev/tests.git (push)
既存アプリだとあんまり使うことはないかも。
clone ☆☆
リモートリポジトリからローカルにもってこれる。名前通りクローン,複製。git 管理もそのままできる。Project を DL するイメージ。
$ git clone git@github.com:MilanistaDev/tests.git
ここだけの話,いろいろやっててブランチがおかしくなったときは,新しいディレクトリに clone して作業再開するのもありです。大きいプロジェクトだと時間かかるので他の作業の裏でやる。
status ☆☆☆☆☆
いまどのブランチにいるんだっけ?
いまどのファイル修正してるんだっけ?
そんなステータスを見たいときに実行する。
$ git status
今いるブランチ,変更ファイル,追加,削除ファイルなどが確認出来る。
最も使うかもしれない。
log ☆☆☆☆☆
これまでのコミットのログを閲覧できる。status と同じくらい使ってる。
$ git log
GitLab でいうところのネットワークみたいなのも確認できる。
$ git log --graph
ブランチの生え方などわかるけどこれは GUI ツールの方が綺麗。
コミットのあとに,ブランチをチェックアウトしたときに正しくブランチが切れているかなど一度確認する。
add ☆☆☆☆☆
ローカルでファイルを編集しました。
よし,ファイルをステージにあげようってときに実行。
コミットする前にアップロードするファイルを add する。
$ git add HogePJ/Controllers/ViewController.swift
status で赤くなってる(Modified)ファイルのパスをコピペでいい。
$ git add .
追跡したくないディレクトリ,ファイルがある場合は,gitignore ファイルを作っておいておく。
編集した覚えのないファイル(xib とか storyboard)を add してしまうと後で面倒なので必ず status をみること。
$ git commit -a -m 'Commit Message'
でもいいけど,必ず status で不要なファイルがないか確認。
commit ☆☆☆☆☆
コミットメッセージはチケット名や PJ 名などを先頭に書き,説明をしっかりかく。
$ git commit -m '修正'
$ git commit -m 'Ticket#23 タブの画像が表示されなかった部分のバグ修正'
$ git commit -m 'タブ改修 タブの画像をそれぞれ適用'
commit は他はそんなに使わないけど,コミットメッセージが適切でなかった場合,1 個前のコミットメッセージを修正する場合は下記を使う。
$ git commit --amend
打つとエディタ(デフォルトならvi)が開くのでミスを修正する。
すでにリモートリポジトリに push してしまったコミットの修正は,
歴史改ざんにあたるため,強制 push をする必要がある。
ローカル(リポジトリ)で修正して,リモート(リポジトリ)にプッシュ時に強制プッシュする。
コミットのタイミングはキリがいいところで行う。
実装前にどの段階でコミットするか考えておくと良い。
複数のファイルにまたがる場合は機能単位,単一(h, m)だとファイル単位みたいな感じ。メソッド単位とかでもいい。
コミットのルールが現場にある場合は従う。
空コミットをする場合は下記コマンドでできます。
GitLab でマージリクエストを作るときとかに書きます。
$ git commit --allow-empty -m '[WIP]空コミット'
push ☆☆☆☆
ローカルリポジトリのコミットをリモートリポジトリにアップロードするときに使う。git add -> git commit -> git push のイメージ。
$ git push origin hogeBranch
Rebase などでコミット履歴の改ざんした場合は,強制(Force) push を行う。オプションは -f。
$ git push -f origin hogeBranch
基本的に -u オプション をつけたほうがいいらしい。
対象のブランチをリモートリポジトリに追跡させる機能。
push のミスとか減らせる?基本的に毎回全部打つスタイルなので
よくメリットがわかってはいない。
$ git push -u origin hogeBranch
リモートブランチを削除する場合は,ローカルで削除後,push する。もしくは,下記のように削除する。
git push リモートリポジトリ :リモートブランチ名
$ git push origin :hogebranch
pull ☆☆☆
リモートリポジトリから変更データをもらってローカルリポジトリに変更を適用する。ユースケースでいうと,いろいろな PJ のブランチが master などにマージされたときに master を最新にするとかそういう感じ(言い回し)で現場では使われる。基本的にブランチを切るときは最新にして切るようにする。
個人で使うときは GitLab の AutoMerge 機能を使ったときのリモートとローカル同期くらいの頻度。
git pull リモートリポジトリ ブランチ名
$ git pull origin master
fetch ☆☆☆
fetch は pull の一個手前って感じ。対象ブランチの更新があれば最新データを引っ張ってきてリモートリポジトリは最新に,ローカルリポジトリ側は変更を適用しない。このブランチ変更あるかなーってときに試しにやってみる感じ。変更等が明確にわかっていれば pull でいいが,不明なときはまずは fetch してみるって感じ。その後変更あれば適宜 pull する。
pull = fetch + merge
リモートリポジトリの hogeBranch の更新
$ git fetch origin hogeBranch
git fetch だけのオプション無しを最近は多く使っている気がする。
一応全部更新したいときは下記を実行する。
$ git fetch --all
checkout ☆☆☆☆☆
ブランチの移動のときに使う。よく使う。
$ git checkout master
ブランチ作って移動もできる。branch コマンドでブランチを作って checkout でそのブランチに移動っていうのをショートカットできる。
$ git checkout -b hogeBranch
加えた変更をなかったことにする,変更した覚えのないファイルの Modified を元に戻す。私の場合は,xib とか Storyboard がほとんど・・・
$ git checkout HogePJ/Views/Main.storyboard
branch ☆☆☆
ローカルリポジトリのブランチを確認する。
$ git branch
リモートリポジトリのブランチも確認したい。
$ git branch -a
ブランチを作りたい。そして移動する。
$ git branch feature/hoge
$ git checkout feature/hoge
// ただこれとイコールなのでこっち推奨
$ git checkout -b feature/hoge
リモートリポジトリに作ったブランチを反映させる。
$ git push origin feature/hoge
ただし,コミットがなければ MR(マージリクエスト)は作れないので注意。
空コミットを作ってプッシュする方法もある。WIP とかつけとくといい。
$ git commit --allow-empty -m '[WIP] Initial Commit'
その後最初のコミットをした段階で Rebase などでコミットをまとめる。
$ git rebase -i HEAD~~
ローカルリポジトリのブランチを消したい。(merge済)
$ git branch -d hogeBranch
ローカルリポジトリのブランチを消したい。(mergeまだ)
$ git branch -D hogeBranch
リモートのブランチを消したい。
それぞれ上記でローカルブランチを消した上で,
$ git push origin :hogeBranch
または
$ git branch --delete hogeBranch
リモートでいらないならローカルでもいらないだろうから前者が多いです。
merge ☆☆☆
他のブランチの内容をマージする。現場では,◯◯のブランチを取り込んでってそういうふうに言う。
git merge 取り込むブランチ名
$ git merge hogeBranch
テストのときとか便利なのがある。マージの一歩手前で止めるもの。
機能 1 のブランチで実装中で他の方が実装している機能 2 を取り込んで軽く動作確認してみてってなときにまだ途中だしマージしたくない・・・スタッシュ(後述)かコミットしてから下記を実行する。
$ git merge --no-ff --no-commit feature/feature2
マージコミットはしない。仮マージ的な感じ。
コミットがないので push ができない。間違ってマージしたものを push することがなくなるのでただの git merge ではなくこちらを推奨。
no fast forward は枝生やしたままマージする感じ。
現場の方針に従うのがいいと思いますが,基本的に --no-ff がいいと思っている。どこでデグレったのかわかりやすいと思うので。
上記のマージを解く(なかったことにする)。
$ git reset --hard HEAD
マージ前の状態に戻るのでそのまま実装を続けます。スタッシュした場合はポップします。
rebase ☆☆☆
マージと同じで取り込むっていう感じだけど,やり方が異なる。
マージは想像通りのマージで,リベースはあたかもマージ後にブランチ切ったようになるイメージ?
$ git rebase master
コンフリクトが起きると解消して continue する必要がある。
$ git rebase --continue
またコンフリクトがあれば同じく止まるので上記を繰り返す。
終わればそのまま作業中のブランチで実装を続ける。
やばいやっぱリベースはや〜めたってときは
$ git rebase --abort
で何事もなかったのように戻る。
rebase した場合は履歴改ざんになるので強制プッシュしなければならない。
コミットのまとめもできる。下記のようなコミットしたあとにミスに気づいて再度コミットした場合,コミット数が増えてしまってしかもかっこ悪い。
$ git commit -m 'Ticket#21 タブのアイコン画像さしかえ'
// タイプミス修正してから・・・
$ git commit -m 'Ticket#21 タイポ(タイプミス)修正'
1 個前のコミットとまとめる。#マークがつく
$ git rebase -i HEAD~~
こういう系は,fixup,squash とかもある。
また機会があれば書く。
まとめたら git log で確認してコミットが修正されていることを確認してプッシュする。すでにリモートリポジトリに push している場合は強制プッシュになる。
Merge か Rebase か
マージはブランチ同士の比較は 1 回,リベースはリベースするのブランチの変更分のコミットの数の分だけ比較する。取り込むブランチのコミット数少ない場合はリベース,多い場合はマージかなぁって,いままでの現場で使ってみてそう思った。あとはコンフリクトが多そうならマージで 1 回で修正するのがいいかなと。リベースだとコミットごとにみるので丁寧にコンフリクト解消したい場合はいいと思う。コンフリクトないならたったったと進んで気持ちがいい。少なくとも取り込む内容は把握した上でどちらかを選ぶようにする。
よくあるであろう事例で見てみる。
ある機能 2 を実装中に別の方が実装した機能 1 が master ブランチにマージされました。最新の master を取り込んでくださいって言われて,git fetch して,git pull origin master して・・・,ここまでは同じ。 マージするか,リベースするか。
Merge
$ git fetch --all
$ git checkout master
$ git pull origin master
$ git checkout feature/feature2
$ git merge master
// コンフリクトがあれば対応(一度にたくさん出ることも)
// マージコミットができるので push
$ git push origin feature/feature2
Rebase
$ git fetch --all
$ git checkout master
$ git pull origin master
$ git checkout feature/feature2
$ git rebase master
// master の新規コミットたちと feature2 の内容を比較
// その比較ごとにコンフリクトがあれば対応して --continue
$ git push -f origin feature/feature2
個人的にはマージコミットがたくさん途中にあるとダサいかなーとか履歴綺麗にしたいとか思うので, Rebase 派だけど現場の方針に合わせてください。
- 比較コミット数が少ない -> どっちでも(Rebase かな)
- コンフリクトが多い -> 丁寧に解消 -> Rebase
- コンフリクトが多い -> コミット数が多い -> Merge
- master に取り込まれたブランチの規模が大きい -> Merge
- master に取り込まれたブランチ数が多い -> Merge
一人でやってるとブランチ切ってマージしてって綺麗な図になるんだけど,チームでやると・・・ね。rebase 使うと多少は綺麗になるっちゃなるんだけど・・・
マージリクエストを出す際は比較ブランチの最新を取得して取り込んだ上で出しましょう。コンフリクトも解消しておくこと。GitLab だと Web 上から Auto Merge できないです。
stash ☆☆☆
スタッシュは退避。例えば作業中のブランチでまだコミットまでは行けそうにないときに違うブランチでの動作確認(クロスチェックなど)を頼まれました。いままでの作業無駄になるのかよ・・・いやそんなことはないですと。
$ git stash
とりあえず,最後にコミットした状態に戻ってしまいます・・・
動作確認終えました。下記コマンドを打って作業中だったブランチに戻ります。
$ git stash pop
作業中だった状態に戻りました。
スタッシュの履歴もあって
$ git stash list
で戻したいやつ(番号)を把握して,
$ git stash pop stash@{2}
で戻ります。
あとは,仮実装しててもういいやってとき,checkout とかで元に戻すのも面倒だから・・・とか,かなり実装したあとに新しいブランチ切るの忘れてたぁぁ・・・,また一からやり直しかよぉぉ・・・とかそういうときに使えます。
reflog ☆
git log はコミットの履歴, git reflog はオペレーション(コマンドとか)の履歴。やらかしてしまったときにみることになるかも。確認だったら 2,3回は使ってる。
reset ☆
同じくやらかしたときに使うことになる。できればあまり使う機会が少ないのが望ましい。リセットなのでなかったことにする系で使う。
いまのところ仮マージ解くくらいしか使ったことはない。
$ git reset --hard HEAD
使う機会があったらまとめます。
diff ☆
difference。コードとかの差分にあたる。でもコマンドラインでうつことは少ないのかもしれない。GitHub とか GitLab とかのツールでみることが多いので。
大事なこと
-
ファイルに不用意に変更を加えない
- コンフリクトの原因になる
- タイポをみつけたときなども含む
- XIB,Storyboard は注意(git checkout ファイル名で対処)
-
少しでもつまったら,迷ったら分かる人に聞く
- まずは調べる->それでもわからなかったら突き進むのをやめる
- Git に詳しい上司とか同僚にまず相談する
- その上で勉強していけばいい(最初からできる人はいない)
- それから次は自分が教える立場になれるようにする
-
ショートカット系で時短を
- 一文字ずつ打ってもいいけど補完機能使える設定を
- タイプミスも減ると思われる
- 記事書きました(Mac + bash)
- 【Mac, bash】git のコマンド補完
- http://milanista224.blogspot.jp/2015/09/git-complement.html
おわりに
Git ができるようになってきたら開発も楽しくなってくる。まだまだマスターには程遠いです。SourceTree みたいな GUI ツールに頼るのもいいけど,エンジニアならターミナル叩いていろいろやってみましょう。前の現場でコマンドラインで分かった上で SourceTree 使ってくださいって言われたのがかなり頭に残ってます。全くその通りだなと。
わからなくなったら変な操作する前に分かる人に聞く
これが一番いいです。教えてもらって次からは対処できればいい。
実践あるのみです。
長文になりましたが,ご覧いただきありがとうございました!!