GitとGitHubの応用

<h1>Gitの仕組み</h1>
Gitは差分ではなくスナップショットとして保存している（高速化が目的）。コミットを辿る事で以前の状態に戻せる

<h1>ローカルは3つのエリアに分かれている</h1>
ワークツリー（ファイルを変更する作業場）
	ステージ（コミットする準備）
	リポジトリ（スナップショットを記録）
	
<h1>Gitのデータ構造（データの管理の仕方）</h1>
・リポジトリに「圧縮ファイル」「ツリーファイル」「コミットファイル」を作成する事でデータ保存をしている。

Gitではこれらのファイルを「Gitオブジェクト」と呼ぶ。Gitオブジェクトは「.git/objects」ディレクトリの下に保存される。
		
・コミットが直前のコミットを持つことで変更履歴を辿ることができる
	・Gitの本質はデータを圧縮して、スナップショットで保存している
	・Gitのコマンドは、そのデータに対して色々な操作をしている
	
	blobオブジェクト（圧縮ファイル）
		ステージングする時に作成されるファイル。
		ファイルの中身を圧縮したもの。実際はハッシュIDで表す。
		圧縮ファイルは構造や名前を持たない
		
	treeオブジェクト（ツリーファイル）
		コミットする時に作成されるファイル。
		ファイル名と圧縮ファイルを組み合わせを保存するもの
		厳密にはツリーファイルの中にツリーファイルが追加されている
		ツリーファイルは圧縮ファイルに構造を与えるためのもの
		
	commitオブジェクト（コミットファイル）
		いつ、誰が、何を、何のために変更したかを記録する
		コミットした時点でのtreeが保存されている
		親コミットを保存している(parnet)
		作成者、日付、メールアドレス、コミットメッセージが記録される
		

<h1>ローカルリポジトリの新規作成</h1>
	$ git init　　　　#.gitディレクトリが作成される
	
.gitディレクトリの中身
		・リポジトリ（圧縮ファイル、ツリーファイル、コミットファイル）
		・インデックスファイル
		・設定ファイル
		
<h1>他の人が既に作成しているプロジェクトから始める場合（GitHub上のプロジェクト）</h1>
	
<h3>1.Gitリポジトリのコピーを作成</h3>
		$ git clone リポジトリ名（GitHub上のURL）
		
		リモートからローカルに複製
			ワークツリー　→ 　ファイルを複製
			リポジトリ　→　.gitを複製
			
<h3>2.変更をステージに追加する</h3>
		$ git add　ファイル名
		$ git add ディレクトリ名
		$ git add .
		
		圧縮ファイルA（リポジトリ）
			index.htmlhファイル内容を圧縮したもの
			
		インデックス（ステージ）
			index.html
			圧縮ファイルA
		
<h3>3.変更を記録する（コミット）</h3>
		$ git commit
		$ git commit -m "メッセージ"
		$ git commit -v　　　　　　　　＃変更差分を表示できる

			
<h3>コミットメッセージの書き方</h3>
			１行目　変更内容の要約
			２行目　空行
			３行目　変更した理由
			
			変更内容の要点と理由を１行で簡潔に書く

<h3>4.現在の変更状況を確認する</h3>
		$ git status
		
		変更途中のファイルなどを間違ってあげないように、どのファイルが変更されたのか確認してからコミットやステージに追加する癖をつける
		
		
<h3>5.何を変更したのか確認する</h3>
		$ git diff　　　　　＃git add前の差分（ワークツリー⇆ステージ）
		$ git diff ファル名　＃個別ファイル
			index.html　⇆　インデックス
		
		$ git diff --staged　＃git add後の差分（ステージ⇆リポジトリ）
			インデックス　⇆　ツリー１　＋　コミット１
		
		コミットやステージに追加する前にどんな変更したかを確認してから追加する癖をつける
		
<h3>6.変更履歴を確認する</h3>
		$ git log
		$ git log --oneline　＃１行で表示する
		$ git log -p ファイル名　＃フィアルの変更差分を表示
		$ git log -n コミット数　＃表示するコミット数を指定
		
		履歴は最新の順から表示する
		
<h3>7.ファイルの削除を記録する</h3>
		ワークツリーとリポジトリからも削除
		$ git rm ファイル名　　　　　＃ファイルごと削除
		$ git rm -r ディレクトリ　　　＃ディレクトリごと削除
		
		リポジトリのみ削除
		$ git rm --cached ファイル名　＃ファイルを残したい時
		
		元の状態に戻したい
		$ git reset HEAD ファイル名
		$ git checkout ファイル名
		
		
<h3>8.ファイルの移動/変更を記録する</h3>
		$ git mv 旧ファイル名　新ファイル名
		
		
<h3>9.GitHubにプッシュする（コミットをリモートリポジトリに上げる）</h3>
		リモートリポジトリを新規登録
		$ git remote add origin GitHub上のリポジトリ（URL）
		
		リモtーリポジトリへ送信
		$ git push リモート名　ブランチ名
		$ git push origin master
		$ git push -u origin master　　＃-u：次回以降git pushのみで送信できるオプション
		
<h3>10.コマンドにエイリアスをつける（コマンドを簡略化する）</h3>
		$ git config --global alias.ci commit　＃ciコマンドに変換
		$ git config --global alias.st status　　＃stコマンドに変換
		$ git config --global alias.br branch　　＃brコマンドに変換
		$ git config --global alias.co checkout　＃coコマンドに変換
		
		git configは設定を変更するコマンド
		--globalをつけるとP C全体の設定になる
			~/.gitconfig
			~/.config/git/config
		--gloabalをつけないと特定のプロジェクトでしか使えない
			今の自分のプロジェクト/.git/config
			
			
<h3>11.バージョン管理したくないファイルを無視するやり方</h3>
		バージョン管理したくないファイル
			パスワードなどの機密情報
			チームの開発で必要のないファイル（自動生成されるファイルやキャッシュなど）
			
		.gitignoreファイルを作成、記述で指定する
			＃から始まる行はコメントとみなされ無視される
			指定したファイルを除外（index.html）
			ルートディレクトリを指定（/root.html）
			ディレクトリ以下を除外（dir/）
			/以外の文字列にマッチ（/*/*.css）
			
			.gitignoreファイル自体はコミットしても問題ない
			
			
<h3>12.変更を元に戻す</h3>
		ワークツリーのファイルを元の状態に戻す（ワークツリー←ステージ）
		$ git checkout -- ファイル名
		$ git checkout -- ディレクトリ名
		4 git checkout -- . 　　　　　　　　＃全変更を取り消す
		
			. ファイル全てを指定
			--　ブランチ名とファイル名が被った時に、どちらを指しているかGitがわからなくなるのを避けるために明示する
			
			ステージの内容をワークツリーと同じにする作業が行われている
		
		
		ステージに追加した変更を元に戻す（ステージ←リポジトリ）
		$ git reset HEAD ファイル名
		$ git reset HEAD ディレクトリ名
		$ git reset HEAD .
		
			ステージの変更を取り消すのみで、ワークツリーには影響を与えない
			内部ではリポジトリから最新のコミット情報を引っ張りステージを上書きする
			
			HEAD　今いるブランチの最新のコミットを明示する
			reset　リセット、上書きすると明示する
			
			
		直前のコミットをやり直す
		$ git commit --amend
		
		注意！　リモートリポジトリにpushしたコミットはやり直したらダメ！
		このコマンドの有効範囲はcommitする前のデータであることが条件！
		
		例）
			リポジトリ（コミットした）
			やり直したい
			ワークツリーで修正
			ステージに追加（$ git add）
			直前のコミットを修正（$ git commit --amend）
			
			
<h3>13.リモートの情報を確認する</h3>
		$ git remote　　＃リモート名を表示
		$ git remote -v　＃対応するURLを表示
		
		設定しているリモートリポジトリの情報を表示する
		
<h3>14.リモートリポジトリの新規追加</h3>
		$ git remote add リモート名 リモートURL
		
		リモート名は省略して追加できる
		
<h3>15.リモートから情報を取得する</h3>
		$ git fetch リモート名
		
		リモートリポジトリ　→　ローカルリポジトリ(remotes/リモート名/ブランチ名)
		ワークツリーには反映されない（$ git merge で反映できる）
		
		備考）
			$ git branch -a
			取得した情報（ブランチ）を確認できる
			
			$ git checkout remotes/リモート名/ブランチ名
			ブランチ名を指定してワークツリーを切り替える
			
			$ git merge リモート名/ブランチ名
			統合したいブランチ名に移動してからブランチ名を取得して実行
			
		git fetchがおすすめ
			
			
<h3>16.リモートから情報を取得する（pull)</h3>
		$ git pull リモート名 ブランチ名
		$ git pull
		
		 リモートリポジトリ　→　ローカルリポジトリ　→　ワークツリー
		
		pullの注意点！
			pullは、現在いるブランチに対してマージまでを一括まで行うコマンド。謝って別のブランチを上書きする危険性がる。
			
		
<h3>17.リモートの情報を詳しく確認する</h3>
		$ git remote show リモート名
		
		表示される情報
			・fetchとpushのURL
			・リモートブランチ
			・git pullの挙動
			・git pushの挙動
			
<h3>18.リモートを変更・削除する</h3>
		変更
		$ git remote nename 旧リモート名 新リモート名
		
		削除
		$ git remote rm リモート名
		
	
<h3>19.ブランチとマージ</h3>
<h5>ブランチ</h5>
並行しながら複数機能を開発するためのもの
			
<h5>ブランチの仕組み</h5>
			Gitのデータの持ち方：リポジト　→　圧縮ファイルA、ツリー１、コミット１
			
				コミット　→　スナップショットを記録している
				スナップショットを時系列順に記録している
				コミットごとに直前の親コミットを記録している
				
			ブランチとはコミットを指したポインタ
				HEAD　＝　自分が今作業しているブランチのこと
				
				ブランチの中身
					最新のコミットIDが格納
					
				HEADの中身
					ブランチ名を格納
					
<h3>ブランチを新規作成</h3>
			$ git branch ブランチ名
			
<h3>ブランチの一覧を表示する</h3>
			$ git branch
			$ git branch -a　＃全てのブランチを表示
			
<h3>ブランチを切り替える</h3>
			$ git checkout 既存のブランチ名
			$ git checkout -b 新ブランチ名　＃-b: ブランチを新規作成して切り替える
			
<h3>変更履歴をマージする</h3>
			$ git merge ブランチ名
			$ git merge リモート名/ブランチ名
			
<h3>マージには３種類ある</h3>
				Fast Forward: 早送りになるマージ
				Auto Merge: 基本的なマージ
				コンフリクト:
					同じファイルの同じ行に対して異なる編集を行なった時
					どちらを優先していいかわからない時にコンフリクトが発生する
					
					例）
						<<<<<<<<HEAD
						HEADの変更部分が表示
						=============
						別のブランチの変更部分が表示
						>>>>>>>>>他ブランチ名
					
					
<h1>コンフリクト関連の事故が起きにくい運用ルール</h1>
複数人で同じファイルを変更しない
pullやmergeする前に変更中の状態をなくしておく（commitやstashをする）
pullする時はpullするブランチに移動してからpullする
コンフリクトしても慌てない

			
		ブランチ名を変更したい
			$ git branch -m ブランチ名
			
		ブランチを削除したい
			$ git branch -d ブランチ名　＃マージされていない変更が残っている場合は削除されない
			$ git branch -D ブランチ名　＃強制削除する
			
		ブランチを利用した開発の流れ
			masterブランチ　→　リリース用ブランチ
			開発　→　トピックブランチを作成して進める
			
		リモートブランチとは
			リモートのブランチ
			
			
<h1>GitHubを利用した開発手順</h1>

	プルリクエスト
		自分の変更したコードをリポジトリに取り込んでもらえるように依頼する機能

	プルリクエストの流れ
		ワークツリー　→　ローカルリポジトリ
			1 masterブランチを最新に更新 ($ git pull リモート名 ブランチ名)
			2 ブランチを作成($ git checkout -b 新ブランチ名)
			3 ファイルを変更($ git add ファイル名)
			4 変更をコミット($ git commit)
		
		ローカル　→　リモートリポジトリ（GitHub)
			5 GitHubへプッシュ($ git push リモート名 ブランチ名)
			6 プルリクエストを送る (GitHub上でリクエストを指定)
			7 コードレビューをお願い(GitHub上でコードレビューを指定)
			8 プルリクエストをマージ
			9 ブランチの削除
			
<h1>GitHub Flowの流れ</h1>
		GitHub社のワークフロー
		
		master -> branch -> プルリクエスト ->master…
		
		1 masterブランチからブランチを作成
		2 ファイルを変更しコミット
		3 同名のブランチをGitHubへプッシュ
		
		4 プルリクエストを送る
		5 コードレビューしmasterブランチにマージ
		6 masterブランチをデプロイ
		
<h1>GitHub Flowを実践する上でのポイント（ 開発フローをシンプルに保ちたい）</h1>
masterブランチは常にデプロイできる状態に保つ
新開発はmasterブランチから新しいブランチを作成してスタート
作成した新しいブランチ上で作業しコミットする
定期的にpushする
masterにマージするためにプルリクエストを使う
必ずレビューを受ける
masterブランチにマージしたらすぐにデプロイする
（テストとデプロイ作業は自動化）
			
			
<h1>リベースで変更履歴を修正する</h1>
<h3>リベースとは</h3>
変更を統合する際に、履歴（分岐）を綺麗に整えるために使うもの。
			
		$ git rebase ブランチ名
		
			ブランチの起点となるコミットを別のコミットに移動する
			
<h3>マージとの違い</h3>
			リベース：　分岐したコミットを残さずにポインタごと移動する
			マージ：　分岐したコミットを残したまま新コミットを生成
			
<h3>リベースの注意点</h3>
GitHubにプッシュしたコミットをリベースするのはNG！
			強制的に上書きしてしまう$git push -fはもちろん絶対NG！
			
<h3>マージかリベースかの考え方</h3>
		マージ
			メリット：コンフリクトの解決が比較的簡単
			デメリット：マージコミットがたくさんあると履歴が複雑化する
			
			結論：作業の履歴を残したい時はマージ
		
		リベース
			メリット：履歴をきれいに保つことができる
			デメリット：コンフリクトの解決が若干面倒（各コミットに解消が必要）
			
			結論：履歴をきれいにしたい場合はリベース
			
		結論
			プッシュしていないローカルの変更　→ 　リベース
			プッシュしているローカルの変更　→ マージ
			コンフリクトしそう（チーム開発やプルリクエストで判断）　→　マージ
			
	
<h3>プルの設定をリベースに変更する</h3>
		プルのマージ型
			$ git pull リモート名 ブランチ名
			
			マージコミットが残るからマージした記録を残したい場合に使う
			
		プルのリベース型
			$ git pull --rebase リモート名 ブランチ名
			
			マージコミットが残らないからGitHubの内容を取得したい時だけに--rebaseを使う
			
			
<h3>リベースで変更履歴を修正する</h3>
コミットをきれいに整えてからPushしたい時は履歴を書き換える
		※GitHubni Pushしていないコミットに限られる
		
		直前のコミットをやり直す
			$ git commit --amend
			リモートリポジトリにPushしたコミットはやり直したらダメ！
			
		複数のコミットをやり直す
			①-I によって対話的リベースモードになる
				$ git rebase -i コミットID
				$ git rebase -i HEAD~3
				
					HEAD = 最新のコミット
					HEAD~1 = HEAD^2　＝　HEADの親コミット
				
					#表示（HEAD~3までを指定部分）
						pick gh21f6d ヘッダー修正
						pick 193054e ファイル追加
						pick 84gha0d README修正
						
							コミットエディッターで表示される
							履歴は古い順に表示される
				
			②やり直したいcommitをeditする
				edit gh21f6d ヘッダー修正
				
			③やり直しを実行
			$ git commit --amend
			
			④次のコミットへ進む（リベース完了）
			$ git rebase --continue
			
			
		コミットを並び替える、削除する
			$ git rebase -i HEAD~3
			
				#表示
					pick gh21f6d ヘッダー修正
					pick 193054e ファイル追加
					pick 84gha0d README修正
					
			
			コミットエディッタ
				①84gha0dのコミット（行）を消す
				②193054eを先に適用する（手動）
				
		コミットをまとめる
			$ git rebase -I HEAD~3
			
			コミットエディッタ
				squash 193054e ファイル追加
				squash 84gha0d README修正
				
		コミットを分割
			$ git rebase -I HEAD~3
			
				#表示
					pick gh21f6d ヘッダー修正
					pick 193054e ファイル追加
					edit 84gha0d READMEとindex修正
			
			$ git reset HEAD^　　　　#コミットを取り消してステージしていない状態まで戻す
			$ git add README
			$ git commit -m 'README修正'
			$ git add index.html
			$ git commit -m 'index.html修正'
			$ git rebase --continue
			
		
<h1>タグの一覧</h1>
		$ git tag　＃全てのタグを表示する
		$ git tag -l "201705"　＃パターンを指定してタグを表示
		
		コミットを参照し易くするためのもの。わかりやすい名前をつけるのがタグ。
		リリースポイントに使う。
		
<h1>タグを作成する</h1>
	
		注釈付き版(annotated)
		$ git tag -a タグ名 -m "メッセージ"
			
			-aオプション：注釈付き
			名前、コメント、署名をつけられる
		
		軽量版（lightweight）
		$ git tag タグ名
		$ git tag タグ名 コミット名　＃後からタグをつける
		
			名前のみつけられる
		
<h1>タグのデータ表示する</h1>
		$ git show タグ名
		
		タグのデータと関連づけられたコミットを表示する
		
		#表示
			タグ付けした人の情報
			タグ付けした日時
			注釈メッセージ
			コミット
			
<h1>タグをリモートリポジトリに送信するやり方</h1>
		$ git push リモート名 タグ名
		$ git push リモート名 --tags　＃タグを一斉送信する
		
		--tagsオプション：ローカルにあってリモートに存在しないタグを送信する
		
	
<h1>作業を一時避難する</h1>
		作業が途中でコミットしたくないけど、別のブランチで作業しないといけない時に使う。
		
		$ git stash
		$ git stash save
		
		stashという場所に一時保管する。
		
<h1>一時避難した作業を確認する</h1>

		$ git stash list
		
<h1>非難した作業を復元する</h1>
		$ git stash apply　　　　＃最新の作業を復元する
		$ git stash apply --index　＃ステージの状況も復元する
		
		$git stash apply スタッシュ名　＃特定の作業を復元する
			スタッシュ名はgit stash listで確認できる
		
	
<h1>一時避難した行を削除する</h1>
		$ git stash drop　＃最新の作業を削除する
		$ git stash drop スタッシュ名　＃特定の作業を削除する
		$ git stash clear　＃全作業を削除する

参考元
[もう怖くないGit！チーム開発で必要なGitを完全マスター/山浦清透](https://www.udemy.com/course/unscared_git/)