8ヶ月間gitを触った今気づいた発見や学び

![ef5f6cbc-0702-1c98-580f-786429f835e5.gif](https://qiita-image-store.s3.amazonaws.com/0/217528/717a5ce1-5bb0-04a9-2264-af3516320030.gif)

　この記事は[aratana Advent Calendar 2017](https://qiita.com/advent-calendar/2017/aratana) 23日目の記事です。

　昨日は@okazono_erikaさんの「[初対面で会う時のドキドキについて](https://qiita.com/okazono_erika/items/6195ff9af351f6e3f5cb)」でした！
　なにやら甘酸っぱいタイトルにつられて本文を拝見すると、ユーザー目線を大切にするお話でした。

---

　プログラミングを触り始めて8ヶ月、エディタ戦争やインデント戦争などたくさんのことを知りました。
　その中から特に、gitについて書きます。
（git関連の本を探しに半径10kmの本屋全部回ったにも関わらず、一冊も見つからず田舎だと再認識しました

　gitの基礎的なことですが、初心者ならではのつまづきや最近の発見や学びを書いていきます。


##ブランチ名の違うブランチに`push`する
　`git push origin ブランチ名`で使う**ブランチ名**が誰をさすのかです。**ブランチ名**については、ローカルとリモートのブランチを指しています。
　つまり`git push origin ブランチ名`とは、ローカルの**ブランチ名**の情報をリモートの**origin/ブランチ名**へと送信しています。

```
git checkout master
git push origin develop

# 上のコマンドはmasterブランチにいながら、
# ローカルのdevelopブランチをリモートのdevelopブランチにpushします
# pushにmasterが関与しないことに注意
```

　上の命令をより詳細に書くと、下のようになります。

```
git push origin develop:develop

# git push origin ローカルブランチ:リモートブランチ
# 
# ローカルのfeatureをリモートのdevelopにpushしたいときは
# git push origin feature:develop
```

##現在のブランチの表示方法
　現在のブランチの確認方法をいくつか表記します。いずれもHEADを使って、現在のブランチを探す方法です。

```
git branch --contains=HEAD
git symbolic-ref --short HEAD
git rev-parse --abbrev-ref HEAD
```

　これらは現在のブランチを**push**するのにいいコマンドがないかと探したときに知ったコマンド群です。また現在のブランチでのコミットを**push**するには下のようなコマンドがおすすめです。


##現在のブランチを`push`する
```
git push origin HEAD

# 普段pushするためにブランチ名を指定したことを省略することができる
# git push origin ブランチ名 と同じ動作
```

　ブランチの指定をすることなく、現在のブランチの情報（HEAD）を**push**することができます。


##HEADを移動する`checkout`
　`git checkout`はブランチ間の移動に使うコマンドだと考えていました。確かにその一面もありますが、正しくはHEADの位置を移動するコマンドです。
　たとえば`git checkout ./`はカレントディレクトリ以下の全ファイルをHEADに移動（直前のコミットの状態に戻す）します。`git reset --hard HEAD`も状態をHEADに戻すコマンドなので、用途が似ているコマンドです。


##統合のコミットを残す`fast-forward`
　**git pull**や**git merge**につけるオプションの一つです。`git pull --ff master`のように使います。**fast-forward**は、『**merge**や**pull**をしたよ』というコミットを作成するか決めるオプションです。
　**fast-forward**をつけると、『**merge**や**pull**をしたよ』というコミットを作成せずHEADを移動させます。逆にコミットを作成したいときは**non fast-forward**設定を付与します。

　コミットを残す利点は、過去の作業を探すとき目印となる点です。逆にコミットを残さない利点は、特に共同開発の現場で同じコミットログを共有できる点です。共同開発の現場では基本的に**merge**は**non fast-forward**で、**pull**は**fast-forward**で行います。

```
# .gitconfigに追加
[merge]
	ff = false
[pull]
	ff = only
```

##push前の再度の確認
　**push**すると、リモートにデータが反映され、コミットの修正が効かなくなります（`git push -f`など例外を除く）。**push**してからコミットを修正しても遅く、他の人に見られてしまいます。
　なので自分が**push**前にしているチェックや作業を記載します。


###コミットを追いかける`git log`
　各ブランチのHEAD位置やコミットコメント、ハッシュ値などが表示されます。
　コミットコメントを読んでも実際のファイル差分に気づかず、想定外のファイル差分を出したことが幾度となくあります。はじめのうちはファイル差分を実際に見ながら作業の確認する以下のようなことをおすすめします。

###親ブランチとの差をみる`git diff 親ブランチ名 子ブランチ名`
　**git diff**は作業したファイル差分を見るだけでなく、ブランチ同士の差分も追いかけることができます。データ量が多く見返すのは大変ですが、確実な方法の一つであると思います。

###コミット内容を追いかける`git log -p`
　`git log`の情報に、各コミットごとのファイル差分が合わせて表示されます。コミットごとに作業を追いかけるので手間ですが、コミットが見やすいかを実感できるコマンドの一つです。
　見やすいコミットのためコミットの編集を行いたいときには、`git rebase`を使います。

###コミットを操作する`git rebase`
　コミットを操作したいとき、綺麗にしたいときに使います。
　`git log`で操作したいコミットを確認します。3個前のコミットを操作したいときには`git rebase -i HEAD~~~`を実行します。

```
pick c74670e delete: お試しで作成したa.txtの削除
pick dc720d9 add: a.txt作成
pick 01a8712 add: b.txt作成

# Rebase 3ff0e5a..01a8712 onto 3ff0e5a (3 commands)
...
```

　と出るので、作業する内容を変えます。
下のような変更ができ、コミットを削除したいときは、コミット一覧の**pick**を**drop**に変更すれば良いです。

|コマンド|説明|
|:--|:--|
|p, pick|そのまま残す|
|r, reword|コミットメッセージの修正|
|e, edit|コミット内容の修正|
|s, squash|直前のコミットに統合（コメントも統合）|
|f, fixup|直前のコミットに統合（コメントは削除）|
|x, exec|シェルコマンドを実行できる。`git stash apply`を挟んだりできる|
|d, drop|コミットを削除|



## まとめ
　ネット上でgit系のコマンドを検索すると、`git push -f origin master`を筆頭に実は危ないコマンドを散見します。初心者はコマンドが危ないことを知らず動作させることが多くあります。ネットに書いてあることを鵜呑みにして、同期の作業を削除したこともあります。でもgitならば、犯人探し`git blame`や作業の確認`git show`、作業の復旧`git cherry-pick`などの作業をくり抜くコマンドに優れているので、共同開発には欠かせないツールの一つであると思います。
　
　まだまだ知らないことも多くgitが怖いですが、自分の武器になりつつある機能の一つです。
　それでは楽しいgitライフを！

---

　明日のエントリーはフロントエンドエンジニアの大先輩@kikuchi_hiroyukiによる『パフォーマンスを意識した要素監視について考える』です！ 楽しみですね！







----
参考
▼Gitでやらかした時に使える19個の奥義
https://qiita.com/muran001/items/dea2bbbaea1260098051

▼git pushの設定
https://qiita.com/masashi127/items/2e103c3fba9d1b058961

▼現在のブランチを取得する
https://blog.hifumi.info/2015/03/28/show-current-branch-name/
https://qiita.com/usamik26/items/8aa6c3aed4b9c7dba5ca