Gitの仕組み
Gitは差分ではなくスナップショットとして保存している(高速化が目的)。コミットを辿る事で以前の状態に戻せるローカルは3つのエリアに分かれている
ワークツリー(ファイルを変更する作業場) ステージ(コミットする準備) リポジトリ(スナップショットを記録)Gitのデータ構造(データの管理の仕方)
・リポジトリに「圧縮ファイル」「ツリーファイル」「コミットファイル」を作成する事でデータ保存をしている。Gitではこれらのファイルを「Gitオブジェクト」と呼ぶ。Gitオブジェクトは「.git/objects」ディレクトリの下に保存される。
・コミットが直前のコミットを持つことで変更履歴を辿ることができる
・Gitの本質はデータを圧縮して、スナップショットで保存している
・Gitのコマンドは、そのデータに対して色々な操作をしている
blobオブジェクト(圧縮ファイル)
ステージングする時に作成されるファイル。
ファイルの中身を圧縮したもの。実際はハッシュIDで表す。
圧縮ファイルは構造や名前を持たない
treeオブジェクト(ツリーファイル)
コミットする時に作成されるファイル。
ファイル名と圧縮ファイルを組み合わせを保存するもの
厳密にはツリーファイルの中にツリーファイルが追加されている
ツリーファイルは圧縮ファイルに構造を与えるためのもの
commitオブジェクト(コミットファイル)
いつ、誰が、何を、何のために変更したかを記録する
コミットした時点でのtreeが保存されている
親コミットを保存している(parnet)
作成者、日付、メールアドレス、コミットメッセージが記録される
ローカルリポジトリの新規作成
$ git init #.gitディレクトリが作成される.gitディレクトリの中身
・リポジトリ(圧縮ファイル、ツリーファイル、コミットファイル)
・インデックスファイル
・設定ファイル
他の人が既に作成しているプロジェクトから始める場合(GitHub上のプロジェクト)
1.Gitリポジトリのコピーを作成
$ git clone リポジトリ名(GitHub上のURL) リモートからローカルに複製
ワークツリー → ファイルを複製
リポジトリ → .gitを複製
2.変更をステージに追加する
$ git add ファイル名 $ git add ディレクトリ名 $ git add . 圧縮ファイルA(リポジトリ)
index.htmlhファイル内容を圧縮したもの
インデックス(ステージ)
index.html
圧縮ファイルA
3.変更を記録する(コミット)
$ git commit $ git commit -m "メッセージ" $ git commit -v #変更差分を表示できるコミットメッセージの書き方
1行目 変更内容の要約 2行目 空行 3行目 変更した理由 変更内容の要点と理由を1行で簡潔に書く
4.現在の変更状況を確認する
$ git status 変更途中のファイルなどを間違ってあげないように、どのファイルが変更されたのか確認してからコミットやステージに追加する癖をつける
5.何を変更したのか確認する
$ git diff #git add前の差分(ワークツリー⇆ステージ) $ git diff ファル名 #個別ファイル index.html ⇆ インデックス $ git diff --staged #git add後の差分(ステージ⇆リポジトリ)
インデックス ⇆ ツリー1 + コミット1
コミットやステージに追加する前にどんな変更したかを確認してから追加する癖をつける
6.変更履歴を確認する
$ git log $ git log --oneline #1行で表示する $ git log -p ファイル名 #フィアルの変更差分を表示 $ git log -n コミット数 #表示するコミット数を指定 履歴は最新の順から表示する
7.ファイルの削除を記録する
ワークツリーとリポジトリからも削除 $ git rm ファイル名 #ファイルごと削除 $ git rm -r ディレクトリ #ディレクトリごと削除 リポジトリのみ削除
$ git rm --cached ファイル名 #ファイルを残したい時
元の状態に戻したい
$ git reset HEAD ファイル名
$ git checkout ファイル名
8.ファイルの移動/変更を記録する
$ git mv 旧ファイル名 新ファイル名9.GitHubにプッシュする(コミットをリモートリポジトリに上げる)
リモートリポジトリを新規登録 $ git remote add origin GitHub上のリポジトリ(URL) リモtーリポジトリへ送信
$ git push リモート名 ブランチ名
$ git push origin master
$ git push -u origin master #-u:次回以降git pushのみで送信できるオプション
10.コマンドにエイリアスをつける(コマンドを簡略化する)
$ 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
11.バージョン管理したくないファイルを無視するやり方
バージョン管理したくないファイル パスワードなどの機密情報 チームの開発で必要のないファイル(自動生成されるファイルやキャッシュなど) .gitignoreファイルを作成、記述で指定する
#から始まる行はコメントとみなされ無視される
指定したファイルを除外(index.html)
ルートディレクトリを指定(/root.html)
ディレクトリ以下を除外(dir/)
/以外の文字列にマッチ(/*/*.css)
.gitignoreファイル自体はコミットしても問題ない
12.変更を元に戻す
ワークツリーのファイルを元の状態に戻す(ワークツリー←ステージ) $ 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)
13.リモートの情報を確認する
$ git remote #リモート名を表示 $ git remote -v #対応するURLを表示 設定しているリモートリポジトリの情報を表示する
14.リモートリポジトリの新規追加
$ git remote add リモート名 リモートURL リモート名は省略して追加できる
15.リモートから情報を取得する
$ git fetch リモート名 リモートリポジトリ → ローカルリポジトリ(remotes/リモート名/ブランチ名)
ワークツリーには反映されない($ git merge で反映できる)
備考)
$ git branch -a
取得した情報(ブランチ)を確認できる
$ git checkout remotes/リモート名/ブランチ名
ブランチ名を指定してワークツリーを切り替える
$ git merge リモート名/ブランチ名
統合したいブランチ名に移動してからブランチ名を取得して実行
git fetchがおすすめ
16.リモートから情報を取得する(pull)
$ git pull リモート名 ブランチ名 $ git pull リモートリポジトリ → ローカルリポジトリ → ワークツリー
pullの注意点!
pullは、現在いるブランチに対してマージまでを一括まで行うコマンド。謝って別のブランチを上書きする危険性がる。
17.リモートの情報を詳しく確認する
$ git remote show リモート名 表示される情報
・fetchとpushのURL
・リモートブランチ
・git pullの挙動
・git pushの挙動
18.リモートを変更・削除する
変更 $ git remote nename 旧リモート名 新リモート名 削除
$ git remote rm リモート名
19.ブランチとマージ
ブランチ
並行しながら複数機能を開発するためのものブランチの仕組み
Gitのデータの持ち方:リポジト → 圧縮ファイルA、ツリー1、コミット1 コミット → スナップショットを記録している
スナップショットを時系列順に記録している
コミットごとに直前の親コミットを記録している
ブランチとはコミットを指したポインタ
HEAD = 自分が今作業しているブランチのこと
ブランチの中身
最新のコミットIDが格納
HEADの中身
ブランチ名を格納
ブランチを新規作成
$ git branch ブランチ名ブランチの一覧を表示する
$ git branch $ git branch -a #全てのブランチを表示ブランチを切り替える
$ git checkout 既存のブランチ名 $ git checkout -b 新ブランチ名 #-b: ブランチを新規作成して切り替える変更履歴をマージする
$ git merge ブランチ名 $ git merge リモート名/ブランチ名マージには3種類ある
Fast Forward: 早送りになるマージ Auto Merge: 基本的なマージ コンフリクト: 同じファイルの同じ行に対して異なる編集を行なった時 どちらを優先していいかわからない時にコンフリクトが発生する 例)
<<<<<<<<HEAD
HEADの変更部分が表示
=============
別のブランチの変更部分が表示
>>>>>>>>>他ブランチ名
コンフリクト関連の事故が起きにくい運用ルール
複数人で同じファイルを変更しない pullやmergeする前に変更中の状態をなくしておく(commitやstashをする) pullする時はpullするブランチに移動してからpullする コンフリクトしても慌てない ブランチ名を変更したい
$ git branch -m ブランチ名
ブランチを削除したい
$ git branch -d ブランチ名 #マージされていない変更が残っている場合は削除されない
$ git branch -D ブランチ名 #強制削除する
ブランチを利用した開発の流れ
masterブランチ → リリース用ブランチ
開発 → トピックブランチを作成して進める
リモートブランチとは
リモートのブランチ
GitHubを利用した開発手順
プルリクエスト
自分の変更したコードをリポジトリに取り込んでもらえるように依頼する機能
プルリクエストの流れ
ワークツリー → ローカルリポジトリ
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 ブランチの削除
GitHub Flowの流れ
GitHub社のワークフロー master -> branch -> プルリクエスト ->master…
1 masterブランチからブランチを作成
2 ファイルを変更しコミット
3 同名のブランチをGitHubへプッシュ
4 プルリクエストを送る
5 コードレビューしmasterブランチにマージ
6 masterブランチをデプロイ
GitHub Flowを実践する上でのポイント( 開発フローをシンプルに保ちたい)
masterブランチは常にデプロイできる状態に保つ 新開発はmasterブランチから新しいブランチを作成してスタート 作成した新しいブランチ上で作業しコミットする 定期的にpushする masterにマージするためにプルリクエストを使う 必ずレビューを受ける masterブランチにマージしたらすぐにデプロイする (テストとデプロイ作業は自動化)リベースで変更履歴を修正する
リベースとは
変更を統合する際に、履歴(分岐)を綺麗に整えるために使うもの。 $ git rebase ブランチ名
ブランチの起点となるコミットを別のコミットに移動する
マージとの違い
リベース: 分岐したコミットを残さずにポインタごと移動する マージ: 分岐したコミットを残したまま新コミットを生成リベースの注意点
GitHubにプッシュしたコミットをリベースするのはNG! 強制的に上書きしてしまう$git push -fはもちろん絶対NG!マージかリベースかの考え方
マージ メリット:コンフリクトの解決が比較的簡単 デメリット:マージコミットがたくさんあると履歴が複雑化する 結論:作業の履歴を残したい時はマージ
リベース
メリット:履歴をきれいに保つことができる
デメリット:コンフリクトの解決が若干面倒(各コミットに解消が必要)
結論:履歴をきれいにしたい場合はリベース
結論
プッシュしていないローカルの変更 → リベース
プッシュしているローカルの変更 → マージ
コンフリクトしそう(チーム開発やプルリクエストで判断) → マージ
プルの設定をリベースに変更する
プルのマージ型 $ git pull リモート名 ブランチ名 マージコミットが残るからマージした記録を残したい場合に使う
プルのリベース型
$ git pull --rebase リモート名 ブランチ名
マージコミットが残らないからGitHubの内容を取得したい時だけに--rebaseを使う
リベースで変更履歴を修正する
コミットをきれいに整えてから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
タグの一覧
$ git tag #全てのタグを表示する $ git tag -l "201705" #パターンを指定してタグを表示 コミットを参照し易くするためのもの。わかりやすい名前をつけるのがタグ。
リリースポイントに使う。
タグを作成する
注釈付き版(annotated)
$ git tag -a タグ名 -m "メッセージ"
-aオプション:注釈付き
名前、コメント、署名をつけられる
軽量版(lightweight)
$ git tag タグ名
$ git tag タグ名 コミット名 #後からタグをつける
名前のみつけられる
タグのデータ表示する
$ git show タグ名 タグのデータと関連づけられたコミットを表示する
#表示
タグ付けした人の情報
タグ付けした日時
注釈メッセージ
コミット
タグをリモートリポジトリに送信するやり方
$ git push リモート名 タグ名 $ git push リモート名 --tags #タグを一斉送信する --tagsオプション:ローカルにあってリモートに存在しないタグを送信する
作業を一時避難する
作業が途中でコミットしたくないけど、別のブランチで作業しないといけない時に使う。 $ git stash
$ git stash save
stashという場所に一時保管する。
一時避難した作業を確認する
$ git stash list
非難した作業を復元する
$ git stash apply #最新の作業を復元する $ git stash apply --index #ステージの状況も復元する $git stash apply スタッシュ名 #特定の作業を復元する
スタッシュ名はgit stash listで確認できる