git 操作#
git について#
Git は、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムです。
Git はスナップショットを記録します。(差分のあるファイルはデータをまるごと保存) なぜスナップショットで記録するのかというとブランチを切ったり、マージしたりする際に、 差分で記録している場合に、差分を再計算が必要となる。スナップショットだと再計算の必要がなく、 複数人による開発が早くなるため。
commit (変更履歴の記録) 手順#
graph LR
ワークツリー --> |git add| ステージ
ステージ --> |git commit| リポジトリ
- ワークツリー:ファイルを変更する作業場(ディレクトリ)
- ステージ:コミットする変更を準備する場
- リポジトリ:スナップショットを記録する場
Git のデータ構造まとめ#
- リポジトリに「圧縮ファイル」「ツリー」「コミット」ファイルを作成することでデータを保存している
- コミットが親子ミットを持つことで変更履歴を辿ることができる
- Gitの本質はデータを圧縮して、スナップショットで記録していること
- Git のコマンドは、そのデータに対していろいろな操作をしている
リポジトリの作成#
ローカルリポジトリの新規作成#
-
git init
-
git init を実行するとカレントディレクトリに.gitディレクトリが作成されます。
commit#
コミットメッセージ#
- git commit -m "[commit message]" にて一行で記述できる
- -m オプションを付けない場合は、編集画面に移行する。
- 変更内容の要点と理由を1行で簡潔に
- 正式に書くとき
- 1行目:変更内容の要約
- 2行目:空行
- 3行目:変更した理由
status / diff#
git status
:ステージの状態を表示git diff
:ワークツリーとステージの間のdiff を表示git diff --staged
:ステージとコミットの間の変更差分を表示
変更履歴を確認する#
git log
git log --online
:1行で表示するgit log -p [ファイル名]
:ファイルの変更差分を表示するgit log -n [コミット数]
:表示するコミット数を制限する
ファイルの削除#
git rm [ファイル名]
git rm -r [ディレクトリ名]
git rm --cached <ファイル名>
:(git の記録を削除)ファイル自体は残したいとき
ファイルの移動(ファイル名の変更)を記録する#
git mv [旧ファイル] [新ファイル]
Tip
以下と同じ * mv <旧ファイル> <新ファイル> * git rm <旧ファイル> * git add <新ファイル>
リモートリポジトリ(Github)を新規追加する#
git remote add origin https://github.com/user/repo.git
origin というエイリアスでurlのリモートリポジトリを登録。 エイリアス指定で、2度目以降のremote リポジトリの指定がoriginで済む
Tip
github のリポジトリのことをoriginとつける慣習がある
リモートリポジトリ(Github)へ送信する#
- 構文:
git push [リモート名] [ブランチ名>]
- 例:
git push origin master
alias の作成#
- git config --global alias.ci commit
- git config --global alias.st status
- git config --global alias.br branch
- git config --global alias.co checkout
Gitの管理から外す#
.gitignore ファイルを作成し、指定する
書き方
-
# から始まる行はコメント
-
指定したファイルを除外 (例) index.html
-
ルートディレクトリを指定 (例) /root.html
-
ディレクトリ以下を除外 dir/
-
/以外の文字列にマッチ「」 //.css
ワークツリーのファイルを元の状態に戻す#
(ワークツリーでの編集を元に戻す)
-
ファイルへの変更を取り消す git checkout --<ファイル名>
git checkout --<ディレクトリ名> -
全変更を取り消す git checkout --
Tip
ワークツリーの状態をステージの状態へ戻している
-- をつけているのはブランチ名とファイル名が被ったときにわかるようにするため。
ステージした変更を取り消す#
-
直前にステージした変更を取り消す git reset HEAD <ファイル名>
git reset HEAD <ディレクトリ名> -
全変更を取り消す git reset HEAD
Tip
指定した変更をステージから取り消すだけなので、ワークツリーのファイルには影響を与えない
直前のコミットを取り消す(remote リポジトリにpushする前)#
git commit --amend
- 使用例
Tip
変更するというより、上書きするイメージ
Warning
リモートリポジトリにPushしたコミットをやり直すのはNG
リモートリポジトリの履歴の状態と他の人がcloneしたリポジトリの履歴に差分が生じ、他の人がPushすることができないため。
リモートの情報を確認する#
リモートリポジトリを登録する#
Tip
リモートリポジトリは複数登録することができる
リモートから情報を取得する(フェッチ)#
git fetch <リモート名>
(例)
git fetch origin
git branch -a にて確認
Warning
リモートリポジトリからローカルリポジトリへ情報を取得してくる
手元のワークツリーへは反映されない。反映するにはgit merge
コマンドを使用する
リモートから情報を取得する(プル)#
git pull <リモート名> <ブランチ名> (例) git pull origin master
Tip
git pull コマンドは git fetch した後に git merge しているのと同じことです
fetch と pull の使い分け#
フェッチを基本的に使うことがおすすめ
master branch にいて何も変更がない場合にプルを使用するなどの運用方法がおすすめ。
Warning
プルは挙動が特殊。カレントディレクトリが取得して来るブランチと異なる場合、意図したブランチと異なるブランチにマージされるため危険。
リモートの詳細情報を表示する#
git remote show <リモート名> (例) git remote show origin
ブランチとマージ#
- 並行して複数機能を開発するためにあるのがブランチ
- コミットはスナップショット、それが時系列順に連なる
- ブランチはコミットファイルを指したポインタ(≒シムリンク)
- コミットしたらブランチが指すコミットファイルが変わる→並行して開発が可能
- ブランチはコミットIDを記録したポインタ
- HEADは現在作業中のブランチへのポインタ
【要約】
- 分岐することで複数の機能を同時並行で開発するための仕組みがブランチ
- ブランチとはコミットを刺すポインタ
(スナップショットによる記録と相まって) - Git はブランチの作成や切り替え、マージが他のバージョン管理ツールより高速
ブランチを新規追加する#
- git branch <ブランチ名>
(例) * git branch feature
Warning
ブランチの切り替えまでは行われない点に注意
Tip
ブランチの一覧を表示
* git branch * git branch -a
Info
git log --online --decorate
ブランチを切り替える#
git checkout <既存ブランチ名>
(例)
git checkout faature
Tip
ブランチを新規作成して切り替える git checkout -b <新ブランチ名>
変更履歴をマージする#
他のブランチでの変更履歴を取り込む。 featureブランチの内容をmasterブランチに取り込みたいとき、HEADはmasterでgit mergeコマンドを実行する
-
FastFoward : 早送りになるマージ(ex. hotfix) ブランチが枝分かれしなかったときはブランチのポインタを前に進めるだけ
-
Auto Merge : 基本的なマージ(ex. feature) 枝分かれして開発していた場合、マージコミットという新しいコミットを作る
git merge <ブランチ名>
git merge <リモート名/ブランチ名>
(例)
git merge origin/master
コンフリクト#
同じファイルの同じ行に対し異なる編集を行う(コンフリクト)
コンフリクトの解決方法#
コンフリクトの事故が起きにくいルール#
- 複数人で同じファイルを変更しない
- pull やmerge する前に変更中の状態をなくしておく(commitやstashをしておく)
- pullするときは、pullするブランチに移動してからpull する
ブランチ名を変更#
git branch -m <ブランチ名>
(例)
git branch -m new_branch
自分が変更しているブランチの名前を変更(-m はmoveの略)
ブランチ名を削除#
git branch -d <ブランチ名>
(例)
git branch -d feature
* -d はdelete の略。master にマージされていない変更が残っている場合削除しない仕組み
* 強制削除は git branch -D <ブランチ名>
にて行う
ブランチを利用した開発の流れ#
master ブランチをリリース用ブランチに、開発はトピックブランチを作成して進めるのが基本。
リモートブランチ#
リモートブランチとはリモートのブランチの状態へのポインタ
Githubを利用した開発手順#
プルリクエスト#
プルリクエストは自分の変更したコードをリポジトリに取り込んでもらえるよう依頼する機能 (レビューによるコードの質の担保のため)
- master ブランチを最新に更新 (ex.) git pull origin maseter
- ブランチを作成 (ex.) git chekout -b pull_request
- ファイルを変更 (ワークツリーでファイルの編集)
- 変更をローカルリポジトリにコミット (ex.) git add → git commit
- Github(リモートリポジトリ)にプッシュ (ex.) git push origin pull_request
- プルリクエストを送る (github上の Pull request タブから実施)
- コードレビュー
- プルリクエストをマージ
- ブランチを削除
Github Flow の流れ#
Github FlowとはGithub社のワークフローのこと。
- master ブランチからブランチ作成
- ファイルを変更し、ローカルリポジトリへコミット
- 同名のブランチをGitHubへプッシュ
- プルリクエストを送る(リモートリポジトリ)
- コードレビューし、master ブランチにマージ(リモートリポジトリ)
- master ブランチをデプロイ
Tip
- master ブランチは常にデプロイできる状態に保つ
- 新開発はmaster ブランチから新しいブランチを作成してスタート
- 作成したブランチ上で作業し、コミットする
- 定期的にpush する
- master にマージするためにプルリクエストを使う
- 必ずレビューを受ける
- master ブランチにマージしたらすぐにデプロイする(テストとデプロイ作業は自動化)
リベース#
変更を統合する際に、履歴をきれいに整えるために使うのがリベース
- ブランチの基点となるコミットを別のコミットに移動する git rebase <ブランチ名>
一連の流れ(FastFoward) * git checkout feature * git rebase master * git checkout master * git merge feature
Tip
git config --global merge.ff false
Warning
GitHubにプッシュしたコミットをリベースしないこと(絶対NG) リモートリポジトリとローカルリポジトリ間のコミット履歴が矛盾し、push できなくなるため (git push -f で強制的に可能だが、履歴が壊れるためこちらもNG)
マージとリベースの使い分け#
マージ#
- コンフリクトの解決が比較的簡単
- マージコミットがたくさんあると履歴が複雑化する
Tip
作業履歴を残したい場合はマージ
リベース#
- 履歴をきれいに保つことができる
- コンフリクトの解決が若干面倒
Tip
作業履歴をきれいにしたい場合はリベース
プッシュしていないローカルの変更にはリベースを使い、プッシュした後はマージを使う。 コンフリクトしそうならマージを使うルールがおすすめ。
プルのマージ型#
- git pull <リモート名> <ブランチ名>
- (例) git pull origin master
Tip
マージコミットが残るから、マージしたという記録を残したい場合に使う
プルのリベース型#
- git pull --rebase <リモート名> <ブランチ名>
- (例) git pull --rebase origin master
Tip
マージコミットが残らないから、GitHubの内容を取得したいだけの時は--rebaseを使うのがおすすめ
プルをリベース型に設定する(--rebaseを付けなくともgit pull の挙動がリベース型になる)#
git config --global pull.rebase true
Master
git config branch.master.rebase true
複数のコミットをやり直す#
git rebase -i <コミットID> (例) 1. git rebase -i HEAD~3
-
やり直したいcommit をedit する
edit xxxx ヘッダー修正
pick yyyy ファイル追加
pick zzzz READEME修正 -
やり直したら以下実行 git commit --amend
-
次のコミットへ進む(リベース完了) git rebase --continue
Tip
HEAD~ (1番目の親を指定する。HEADを基点にして数値分の親コミットまで指定する)
HEAD^ (マージした場合の2番目の親を指定する)
rebase -i コマンドの一連の流れ#
- git rebase -i コマンドで対話的リベースモードに入る
- 修正したいコミットをedit にしてコミットエディタを終了する
- edit コミットのところでコミットの適用が止まる
- git commit --amend コマンドで修正
- git rebase--continue で次のコミットへ行く
- pickだとそのままのコミット内容を適用して次へ行く
コミットを並び替える、削除する#
git rebase -i <コミットID> 後に削除、順番を入れ替えればOK
コミットをまとめる#
git rebase -i <コミットID> 後にpick
の部分をsquash
指定
コミットを分割する#
(例)
git rebase -i HEAD~3
pick xxxx ヘッダー修正
pick yyyy ファイル追加
pick zzzz READMEとindex修正
↓
pick xxxx ヘッダー修正
pick yyyy ファイル追加
edit zzzz READMEとindex修正
$ git reset HEAD^
$ git add README
$ git commit -m 'README修正'
$ git add index.html
$ git commit -m 'index.html修正'
$ git rebase --continue
タグ一覧を表示する#
タグを作成する#
Note
基本的には注釈つきタグで
タグのデータを表示する#
git show [タグ名]
タグをリモートリポジトリに送信する#
git push [リモート名] [タグ名]
タグを一斉に送信する#
git push [リモート名] --tags
作業を一時避難する#
git stash
避難させた作業を確認する#
git stash list
避難させた作業を復元#
# 最新の作業を復元する
git stash apply
# ステージの状況も復元する
git stash apply --index
# 特定の作業を復元する
git stash apply [スタッシュ名もしくは番号]
(例)
git stash apply stash@{1}