Gitを学習したので備忘録を残す
はじめに
Git についてこれまでプロジェクトの開発で使ってきたが、未だ自信が無いため改めて学習した。
今後の自身の開発を進めていく中でも学習した内容をリファレンスとして活用するために記録。
概要
Git:ファイルのバージョン管理をするためのシステム
バージョン管理をすることで、いつでも誰かが変更したバージョンに戻ることができる。
GitHub:コードのホスティングサービス
特徴
- プルリクエストで複数人開発
- 世界中のチームが GitHub 上で開発
Git の初期設定
- Git のインストール
- GitHub の登録
- .gitconfig ファイルへの設定情報の登録
- ユーザーネーム登録
git config --global user.name "git user name"
- メールアドレス登録
git config --global user.email github@example.com
- エディタ登録
git config --global core.editor "atom --wait"
- 登録結果の確認(個別)
- ネーム:
git config user.name
- メール:
git config user.email
- エディタ:
git config core.editor
- ネーム:
- 登録結果の確認(一括全て表示)
git config --list
※上記の登録データは全て、ホームディレクトリ配下の.gitconfig ファイルに設定されている。
基本編
Git の仕組みと基本的なコマンド
Git はデータをスナップショットを記録する。
→ 複数人が並行して開発できるようにするため
バージョン変更の記録:コミット
→ 現在のバージョンと直前のバージョンを保存する
ローカルからリモートへの保存の概念
ワークツリーで変更したバージョンのスナップショットを記録することで、ローカルリポジトリに保存する。
ローカルリポジトリに保存した内容を GitHub(リモートリポジトリ)にアップする。
- リポジトリ:履歴置き場のデータベース
- ローカルリポジトリ:自分の PC 上の履歴データの保管場所
- ワークツリー:自分の PC の作業場所
ローカルのイメージ
ローカルは 3 つのエリア(ワークツリー → ステージ → リポジトリ)に分かれている
- リポジトリ:前述の通り
- ステージ:コミットする変更を準備する場所
- ワークツリー:前述の通り
Git を始めよう(GitHub にリポジトリ作成したい場合はここから参考)
自分でローカルリポジトリに新規プロジェクトを作成して git init から始める方法
- シェル上でプロジェクトのディレクトリを作成し、作成したディレクトリに移動する
- 移動先のディレクトリのトップレベルで、ターミナルで git init を入力する
.git ディレクトリが作成される。.git ディレクトリがローカルリポジトリの正体。この中に git で必要なことがほとんど含まれている。 - .git ディレクトリの中身
○ リポジトリ:圧縮ファイル、ツリーファイル、コミットファイル
○ インデックス
○ 設定ファイル - ls -a で.git ディレクトリが作成されていることを確認。.git ディレクトリ内ではまず以下 2 つが重要。
- objects ディレクトリ:リポジトリの本体
- config ファイル:git の設定ファイル
GitHub 上から始めよう
他人が既に作成したプロジェクトの Git リポジトリのコピーを作成する方法
- GitHub で必要なディレクトリから Git リポジトリの URL をコピーする
- 自分の PC で、クローンを作成したいディレクトリの最上位に移動する
- git clone <リポジトリ名>で、クローン(コピー)を作成する
git clone コマンドを打つことで以下の 2 点のコピーが行われる- ワークツリーに、リモートリポジトリのファイルがコピー
- ローカルリポジトリに、.git ディレクトリがコピー
変更の保存方法
- 変更をステージに追加する
git add <ファイル名>
git add <ディレクトリ名>
git add .
ワークツリーからステージに追加する
※ステージが存在する目的:コミットする変更を準備
- 変更を記録する
変更を記録すること:コミット
git commit
git commit -m "<メッセージ>"
git commit -v
-v:ファイルの変更内容を確認できる
ステージからリポジトリに、スナップショットを記録する
- 現在の変更状況を確認する
git status
- 変更差分を確認する
- git add する前の変更分
git diff
git diff <ファイル名>
- git add した後の変更分
git diff --staged
- 変更履歴を確認する
git log
git log --oneline
一行で表示する
git log -p index.html
ファイルの変更差分を表示する
git log -n <コミット数>
表示するコミット数を制限する
- ファイルの削除を記録する
ファイルの削除を記録するには、git add とは別のコマンドを使う必要がある
git rm <ファイル名>
git rm -r <ディレクトリ名>
ファイルごと削除する
git rm --cached <ファイル名>
ファイルを残したい時(git の記録には残したくない時)
- ファイルの移動を記録しよう
git mv <旧ファイル名> <新ファイル>
以下のコマンドと同じ
mv <旧ファイル名> <新ファイル>
git rm <旧ファイル名>
git add <新ファイル>
- GitHub にプッシュしよう
- 事前準備 ①:GitHub でリモートリポジトリを新規作成する
GitHub サイトのマイページで your profile からリポジトリを新規作成する - 事前準備 ②;リモートリポジトリ(GitHub)をローカルに新規追加する
git remote add origin <リモートリポジトリのURL>
→origin というショートカットで URL のリモートリポジトリを登録するという意味
- 次にやること:リモートリポジトリ(GitHub)へ送信する
git push <リモート名> <ブランチ名>
git push origin master
※git push -u origin master と入力しておくことで、次回以降は git push のみで同様の処理を行う
- コマンドにエイリアスをつける
エイリアス:別名
git config --global alias.ci commit
→commit というコマンドに ci というコマンドを割り当てており、次回以降は ci と入力すれば commit コマンドが実行されることを意味する
git config --global alias.st status
git config --global alias.br branch
git config --global alias.co checkout
- バージョン管理したくないファイルを無視する方法
.gitignore ファイルに以下のように指定する
- ファイル名を指定した場合は、指定したファイルを除外:index.html
- ルートディレクトリを指定:/index.html
- ディレクトリ以下を除外:dir/
- /以外の文字列にマッチ://.css
実践編
変更を元に戻す
- ワークツリーに存在するファイルへの変更を取り消したい時
実際の処理:ステージの状態をワークツリーに反映している
git checkout -- <ファイル名>
git checkout -- <ディレクトリ名>
全変更を取り消す
git checkout -- .
- ステージに追加した変更を元に戻したい時
実際の処理:リポジトリから最新のコミット情報を取得して、ステージの内容を上書きしている。
→ 指定した変更をステージから取り消すだけなので、ワークツリーのファイルには影響を与えない
git reset HEAD <ファイル名>
git reset HEAD <ディレクトリ名>
前変更を取り消す
git reset HEAD .
- 直前のコミットを修正したい時
実際の処理:現在のステージの状態を元に直前のコミットをやり直す
git commit --amend
※リモートリポジトリに PUSH したコミットはやり直してはいけない!
既にリモートリポジトリに PUSH した後で修正したい場合は、普通に git commit コマンドでコミットしたものを PUSH するようにする
GitHub とやりとりする
- リモートの情報を確認する
設定しているリモートリポジトリの情報を表示するコマンド
git remote
対応する URL を表示
git remote -v
- リモートリポジトリを追加する
git remote add <リモート名> <リモートURL>
git remote add tutorial http://github.com/~~~/~~.git
tutorial というショートカットで URL のリモートリポジトリを登録する
git push -u bak master
- リモートから取得する(フェッチ編)
git fetch <リモート名>
git fetch origin
fetch:取ってくる
git fetch を使うと、リモートリポジトリからローカルリポジトリの remotes/リモート/ブランチというリモートブランチに情報を落としてくる。
※リモートからローカルリポジトリに情報を取得するが、ワークツリーには反映されない
ワークツリーに反映させるためには、git merge を使って統合させる必要がある。
git branch -a
-a は all の略。Git branch にある全ての情報を取得という意味。
git checkout remotes/origin/master
remotes/origin/master にワークツリーの内容を切り替える
git merge origin master
origin リポジトリの master ブランチの内容を自分のワークツリーに統合するという意味
- リモートから取得する(プル編)
Git pull は、リモートから情報を取得してマージまでを一度にやりたい時に使う。
git pull <リモート名> <ブランチ名>
git pull origin master
上記コマンドは省略可能
git pull
これは下記コマンドと同じこと
git fetch origin master
git merge origin/master
-
フェッチとプルを使い分ける
基本的には git fetch を使うのがおすすめ。
git pull は挙動が特殊なので気をつけて使う必要がある。
プルの注意点
・git pull origin hoge をすると、自分のローカルリポジトリの remotes/origin/hoge ブランチに情報を取得するが、そのローカルリポジトリの hoge ブランチの内容がワークツリーの master ブランチに統合されてしまう
・ワークツリー上で自分が merge ブランチにいて何も変更を加えていない時のみ git pull を使うようにした方が良い -
リモートの情報を詳しく知る
リモートの詳細情報を表示したい時のコマンド
git remote show <リモート名>
git remote show origin
git remote コマンドよりも詳しい情報を表示する
※表示される内容
- Fetch と Push の URL
- リモートブランチ
- git pull の挙動
- git push の挙動
- リモートを変更・削除する
別のリモート名を使いたくなった時のコマンド(変更)
git remote rename <旧リモート名> <新リモート名>
git remote rename tutorial new_tutorial
リモートを使わなくなった時のコマンド(削除)
git remote rm <リモート名>
git remote rm new_tutorial
ブランチとマージを使いこなす
-
ブランチとは何か?
ブランチの存在意義:並行して複数機能を開発するためにある
ブランチを分岐して開発することで、他の人の変更に影響されない -
ブランチの仕組み
Git のデータの持ち方
Git add で圧縮ファイルが作成され、git commit でツリーファイルとコミットファイルが作成される。
コミットはスナップショットであり、親コミットを保持している。それが時系列順に連なる。
ブランチ:コミットを指したポインタ
→ コミット ID を記録している
HEAD:今自分が作業しているブランチを指し示したポインタ
→ref: feature(ref は参照の意味。feature ブランチを参照しているということ)
コミットしたらブランチが指し示すコミットファイルが変わる。
ブランチや HEAD というファイルはリポジトリに登録されている(HEAD は.git/HEAD、ブランチは.git/refs/にそれぞれ登録されている)
- ブランチの新規作成
Git branch <ブランチ名>
Git branch feature
ブランチ作成するだけで、ブランチの切り替えまでは行わない。
ブランチの一覧を表示する
Git branch
全てのブランチを表示する
Git branch -a
なんのブランチがあるかを確認したい時に使う
それぞれのブランチがどのコミットを指しているかを確認したい
git log --oneline --decorate
--decorate で、どのブランチがどのコミットを指しているかが表示できる
- ブランチを切り替える
git checkout <既存ブランチ名>
git checkout feature
Git の内部では、HEAD の位置を指し示すブランチを切り替えている
ブランチを新規作成して切り替える
git checkout -b <新ブランチ名>
-b をつけるとブランチの新規作成と切り替えを一度に行える
- 変更をマージする
マージとは、他の人の変更内容を取り込むこと
git merge <ブランチ名>
git merge <リモート名/ブランチ名>
git merge origin/master
作業中のブランチにマージする
マージには 3 種類ある
- Fast Forward:早送りになるマージ
ブランチが枝分かれしていない場合、master ブランチにいる状態で git merge hotfix と打つと、ブランチのポインタを前に進めるだけ - Auto Merge:基本的なマージ
master ブランチにいる状態で git merge feature を実行すると、feature ブランチの内容を取り込んだ新しい master ブランチが作成される
枝分かれして開発している場合、マージコミットという新しいコミットを作成する - コンフリクト
コンフリクトはどのような時に怒るか?→ 同じファイルの同じ行に対して異なる編集を行った時。
コンフリクトが起きないようにするにはどうすればいいか?
- 複数人で同じファイルを変更しない
- pull や merge をする前に変更中の状態を無くしておく(commit や stash をしておくのが良い)
- pull するときは、pull するブランチに移動してから pull する
- コンフリクトしても慌てない
- ブランチを変更・削除したい時
- ブランチ名を変更したい時
Git branch -m <ブランチ名>
Git branch -m new_branch
自分が作業しているブランチの名前を変更する
- ブランチを削除したい時
Git branch -d <ブランチ名>
Git branch -d feature
-d は安全であるため、master にマージされていない変更が残っている場合そのブランチは削除しない
強制削除する
Git branch -D <ブランチ名>
-
ブランチを利用した開発の流れ
master ブランチをリリース用ブランチにし、開発はトピックブランチを作成して進めるのが基本。 -
リモートブランチとは何か?
リモートブランチ:リモートのブランチの状態へのポインタ
Git fetch すると、リモートブランチは<リモート>/<ブランチ>で参照できる。
GitHub を利用した開発手順の流れ
プルリクエストの流れ
プルリクエストは、自分の変更したコードをリポジトリに取り込んでもらえるように依頼する機能 1. ワークツリーで master ブランチを最新に更新 2. ブランチを作成 3. ファイルを変更 4. 変更をコミット(コミットするとローカルリポジトリにコミットファイルが作成される) 5. GitHub へプッシュ 6. GitHub(リモートリポジトリ)にてプルリクエストを送る 7. コードレビューを受ける 8. プルリクエストをマージする 9. ブランチを削除する
GitHub 上での操作
-
プルリクエストの作成
・リポジトリのページに入る
・Pull Requests タブで New pull request ボタンを押下する
・base: master、compare: pull_request を選択する
→compare にはプルリクエストする側を選択する。base は基盤となるブランチ
・create pull request ボタンを押下する
・タイトル本文を記載の上で、Create pull request ボタンを押下する -
コードレビュー依頼の作成
・右サイドバーの Reviewers でレビューをお願いしたい人を選択する
・レビュワーはメールで通知を受けるので、そこからサイトに入って Pull requests タブに入る
・依頼されたプルリクエストを選択し、Files changes(今回のプルリクエストでの変更したファイルが確認できる)を見る
・コメントを通じて修正をしていく
・必要なレビューと修正が全て終わったら、レビュワーは File changes の右側にある Review changes を押下して、Approve を選択した上で Submit review ボタンを押下すると、プルリクエストを Approve できる。
・コンフリクトなども全部解消できていたら、Merge pull request ボタンを押下する →confirm merge ボタンを押下する
・不要になったブランチを削除する
コンフリクト解消を自力で解決する工程
→GitHub 上での変更をローカル上に取り込めていなかったことで発生。自分の master ブランチを GitHub 上の master ブランチに合わせる。
git branch -D master
ローカルの master ブランチを削除
git fetch
GitHub のリポジトリの情報を取得
git branch master origin/master
origin リポジトリの master から自分のローカルの master ブランチを作成できる
git merge origin/master
pull_request ブランチでリモートの master ブランチの内容を取り込む
GitHub Flow の流れ
GitHub Flow とは?
GitHub 社のワークフロー。master→branch→ プルリクエスト →master のサイクル。
GitHub Flow の流れ
1. masterブランチからブランチを作成
2. ファイルを変更しコミット
3. 同名のブランチをGitHubへプッシュ
4. プルリクエストを送る
5. コードレビューし、masterブランチにマージ
6. masterブランチをデプロイ(リリース)
GitHub Flow を実践する上でのポイント
・master ブランチは常にデプロイできる状態に保つ
・新規開発は master ブランチから新しいブランチを作成してスタート
・作成した新しいブランチ上で作業しコミットする
・定期的に PUSH する
・master にマージするためにプルリクエストを使う
・必ずレビューを受ける
・master ブランチにマージしたらすぐにデプロイする(テストとデプロイ作業は自動化)
リベースで変更履歴を修正する
- リベースについて
リベース:変更を統合する際に、履歴をきれいに整えるために使うのがリベース
リベースで履歴を整えた形で変更を統合するコマンド
git rebase <ブランチ名>
ブランチの基点となるコミットを別のコミットに移動する
ブランチの親ブランチを変更することで内容を取り込む
リベースの一連の作業の流れ
Git checkout feature
Git rebase master
Git checkout master
Git merge feature
→ リベースを使うことで、履歴を一直線にした上で他のブランチの変更内容を取り込むことができている(Fast Forward なのでマージコミットが発生しない)
リベースとマージの違い
→ リベースは履歴が一直線になり、マージは履歴が枝分かれする。
-
リベースでしてはいけないこと
「GitHub にプッシュしたコミットをリベースするのは NG」
→ ローカルとリモート(GitHub)でコミットの次のコミットが異なることになるので PUSH できなくなる。
→git push -f は絶対 NG!!! -
リベースとマージのどちらを使う?
マージかリベースかは Git の運用方法次第
-
マージの特徴
+:コンフリクトの解決が比較的簡単
ー:マージコミットがたくさんあると履歴が複雑化する
→ 作業の履歴を残したいならマージを使おう! -
リベースの特徴
+:履歴をきれいに保てる
ー:コンフリクトの解決が若干面倒(コミットそれぞれに解消が必要)
→ 履歴をきれいにしたいならリベースを使おう! -
使い分けの方針のおすすめ
・プッシュしていないローカルの変更にはリベースを使う
・プッシュした後はマージを使う
・コンフリクトしそうならマージを使う
- プルの設定をリベースに変更する
プルにはマージ型とリベース型がある
- プルのマージ型
Git pull <リモート名> <ブランチ名>
Git pull origin master
→ マージコミットが残るから、マージしたという記録を残したい場合に使う
- プルのリベース型
Git pull --rebase <リモート名> <ブランチ名>
Git pull --rebase origin master
→ マージコミットが残らないから、GitHub の内容を取得したいだけの時は--rebase を使うのがおすすめ
デフォルトでプルをリベース型に設定できる
Git config --global pull.rebase true
master ブランチで git pull する時だけ
Git config branch.master.rebase true
--rebase オプションをつけなくても git pull の挙動がリベース型になる
※設定ファイル
--global をつけると PC 全体の設定になる(~/.gitconfig、や ~/.config/git/config)
つけないと個別のローカルリポジトリの設定になる(project/.git/config)
- リベースで履歴を書き換える(1)
コミットをきれいに整えてから push をしたいときは履歴を書き換えよう(※GitHub に push してない時)
直前のコミットをやり直すコマンド
git commit --amend
複数のコミットをやり直すコマンド
Git rebase -i <コミットID>
※-i は--interactive の略。対話的リベースモードとして、やりとりしながら履歴し変更していく
Git rebase -i HEAD~3
※HEAD から 3 つ遡った親コミットを基点として、それ以降のコミットをリベースするという意味
= HEAD~2, HEAD~1, HEAD の内容を修正するということ
上記のコマンドを実行すると、コミットエディタが出てきて以下のように表示される
pick hswj83s ヘッダー修正
pick k04uenv ファイル追加
pick 39e8ehe README修正
上記のやり直したい commit をpick
からedit
に修正する。
修正したらコミットエディタをステージに保存して終了する。
自分のローカル上でgit commit --amend
で修正する。
上記ができたらgit rebase --continue
コマンドでリベースを完了して、次のコミットへ進む。
- リベースで履歴を書き換える(2)
コミットを並び替える、削除する
Git rebase -I HEAD~3
履歴は古い順に表示される(一番下にあるのが最新)
最新のコミットを消す。
一番古いものと2番目に古いものを並び替える。
コミットをまとめる方法
Git rebase -i HEAD~3
pick
の代わりにsquash
を指定する。そうすると、そのコミットを直前のコミットと一つにまとめる。
コミットを分割する
Git rebase -I HEAD~3
分割したいコミットをpick
の代わりにedit
に修正する。
コミットエディタを保存終了したら、以下のコマンドを実施。
Git reset HEAD^
→git reset はコミットを取り消してステージングしてない状況まで戻すこと。HEAD^のコミット(edit にしたコミット)を取り消してステージングする前の状態に戻す。
Git add README
Git commit -m "README修正"
Git add index.html
Git commit -m "index.html修正"
Git rebase --continue
タグづけをする
- タグの一覧を表示する
タグ:コミットを参照しやすくするためにわかりやすい名前をつけること。よくリリースポイントに使う。
タグの一覧を表示するコマンド
git tag
パターンを指定してタグを表示
git tag -l "202705"
→git tag コマンドはアルファベット順にタグを表示する
- タグを作成する
タグには、注釈付き(annotated)版と軽量(lightweight)版の 2 種類がある。
- 注釈付き:通常使うしっかりと情報をつけたタグ
- 軽量版:情報量を減らした省略版
注釈付きタグを作成する
Git tag -a [タグ名] -m "[メッセージ]"
Git tag -a 20170520_01 -m "version 20170520_01"
-a オプションをつけると注釈付きタグを作成する。-m オプションをつけるとエディタを立ち上げずにメッセージ入力できる。
名前、コメント、署名をつけれる。
軽量版タグを作成する
Git tag [タグ名]
Git tag 20170520_01
後からタグ付けする
Git tag [タグ名] [コミット名]
Git tag 20170520_01 8a6cbc4
オプションをつけないと軽量版タグを作成する。
名前のみつけれる。
タグのデータを表示する。
Git show [タグ名]
Git show 20170520_01
タグのデータと関連づけられたコミットを表示する。
- タグをリモートリポジトリに送信する
タグをリモートに送信するには、git push コマンドで別途指定する
Git push [リモート名] [タグ名]
Git push origin 20170520_01
タグを一斉に送信する
Git push origin --tags
--tags をつけるとローカルにあってリモートリポジトリに存在しないタグを一斉に送信する。
スタッシュで作業を一時退避する
- 作業を一時退避しよう
作業が途中でコミットをしたくないけど、別のブランチで作業しないといけない。
そういう時に作業を一時避難するコマンド。
Git stash
Git stash save
stash は隠すの意味。上記は同じ意味のコマンド。
stash に保管する。
- 避難した作業を確認しよう
Git stash list
避難した作業に一覧を表示する
- 避難した作業を復元しよう
- 最新の作業を復元する
Git stash apply
ステージの状況も復元する
Git stash apply --index
- 特定の作業を復元する
Git stash apply [スタッシュ名]
Git stash apply stash@{1}
apply は適用するの意味
- 避難した作業を削除しよう
- 最新の作業を削除する
Git stash drop
- 特定の作業を削除する
Git stash drop [スタッシュ名]
Git stash drop stash@{1}
- 全作業を削除する
Git stash clear