GitとGithub
Gitとは
Gitとはバージョン管理システムのこと。自分のPC内(ローカル)で使う。
Gitによってファイルをいつ、誰が、どのように編集したかを履歴に残して管理できる。
Githubとは
GithubとはGitを使ったホスティングサービスのこと。Githubはインターネット上(リモート)で履歴を管理する。
Githubによって複数人でコードを共有し開発をすることができる。
Gitの仕組み
Gitはファイルの情報をスナップショットで保存する。スナップショットとは、Gitに追跡されているすべてのファイルのバックアップである。変更の差分を保存しているのではなく、変更前の状態と変更後の状態をそれぞれの履歴として保存しているということである。
このスナップショットのおかげで、前のバージョンに戻したり、差分を計算せずにブランチを切ったり、マージしたりすることが簡単に行える。
Gitで変更を保存する流れ
- Gitを初期化する
- ローカル(自分のPC内)でファイルを変更する
- ステージングに追加する
- ローカルリポジトリにコミットする
- Githubにプッシュする
1 Gitを初期化する
まずはGitでバージョン管理したいプロジェクトでgit init
を行う。このコマンドによってGitが初期化され、ローカルリポジトリが作られる。
git init
リポジトリとは、スナップショットが保存される場所。自分のPC内に作られるリポジトリをローカルリポジトリといい、反対にインターネット上に作られるリポジトリのことをリモートリポジトリという。
ローカルリポジトリは具体的には.gitディレクトリ
のこと。このディレクトリにGitに必要な情報や履歴が保存される。
2 ローカルでファイルを変更する
Gitの初期化が行われたプロジェクトでファイルを作成したり、コードを記述したりする。この作業を行う場所をワークツリーともいう。
3 ステージングに追加する
変更を記録する前にgit add
でワークツリーにある変更をステージと呼ばれる場所に追加する。ステージとはコミットする変更を準備する場所のこと。
ステージによって変更した部分だけをコミットすることができる。
// ファイルを指定して変更をステージに追加する
git add [ファイル名]
// 変更されているファイルを全てステージに追加する
git add .
4 ローカルリポジトリにコミットする
ステージにある変更をgit commit
でコミットする。コミットとはスナップショットをリポジトリに保存することである。
// CUIのエディタでコミットメッセージを入力する
git commit
// コマンドと一緒にコミットメッセージを入力する
git commit -m "コミットメッセージ"
コミットを行う際はコミットメッセージも合わせて記録する。コミットメッセージにはコミットの内容や理由を記述する。
ここまでの作業(変更→ステージに追加→コミット)でローカルリポジトリに変更を記録することは完了する。
5 Githubにプッシュする
Githubにローカルリポジトリの内容を保存するにはgit push
を使う。Githubにプッシュすることで、他の開発メンバーとコードを共有できる。
プッシュする前に、リモートリポジトリを作成しておく。
git remote add origin [URL]
originというのはリモートリポジトリのURLのショートカットのようなもの。
リモートリポジトリを作成している状態で、Githubにプッシュする。
git push [リモート名] [ブランチ名]
// 2回目のプッシュ以降はgit pushだけでプッシュできるようにするオプション
git push -u origin master
その他のGitの操作
ファイルの削除を記録する
ファイルの削除を記録するにはgit rm
を使う。
// ファイルごと削除する
git rm [ファイル名]
// ディレクトリを削除する
git rm -r [ディレクトリ名]
// ワークツリーのファイルを残してリポジトリのファイルは削除する
git rm --cashed [ファイル名]
ファイルの移動を記録する
ファイルの移動を記録するにはgit mv
を使う。
git mv [旧ファイル名] [新ファイル名]
ファイルの変更を取り消す
ファイルの変更を取り消すにはgit checkout --
を使う。--
がついているのはブランチの切り替えに使うgit checkout
と区別するため。
git checkout -- [ファイル名]
git checkout -- [ディレクトリ名]
// 全ての変更を取り消す
git checkout -- .
ステージに追加した変更を取り消す
ステージに追加した変更を取り消すにはgit reset HEAD
を使う。ステージの追加を取り消すため、ワークツリーのファイルの変更は残ったままである。
HEADというのは、今自分がいるブランチの最新のコミットを表す。つまりステージに追加された変更を最新のコミットで上書きすることになる。
git reset HEAD [ファイル名]
git reset HEAD [ディレクトリ名]
// 全ての変更を取り消す
git reset HEAD .
直前のコミットを上書きする
直前のコミットを上書きするにはgit commit --amend
を使う。
リモートリポジトリにプッシュしたコミットは取り消してはいけない。
プッシュしたコミットを取り消したいときは、新しいコミットを作って修正する。
git commit --amend
直前のコミットを取り消す
直前のコミットを取り消すにはgit reset [オプション] HEAD^
を使う。
// コミットだけが取り消される(ステージ、ワーキングツリーはそのまま)
git reset --soft HEAD^
// コミットとステージが取り消される(ワーキングツリーはそのまま)
git reset --mixed HEAD^
// コミット、ステージ、ワーキングツリー全て取り消される()
git reset --hard HEAD^
特定のコミットを取り消す
特定のコミットを取り消すにはgit revert
を使う。
git revert [コミットID]
revertは新しいコミットを作成して取り消すので、プッシュ済みのコミットに対して使える。resetはコミットそのものを取り消してしまうので、親のコミットを取り消してしまった場合他の開発メンバーがプッシュできなくなる。
変更履歴を確認する
変更履歴を確認するにはgit log
を使う。
git log
// 一行で表示する
git log --oneline
// 変更差分を表示する
git log -p [ファイル名]
// 表示するコミット数を制限する
git log -n [コミット数]
変更差分を確認する
変更の差分を確認するにはgit diff
を使う。
// git addする前の変更差分
git diff
// git addした後の変更差分
git diff --staged
現在の変更状況を確認する
変更されたファイルを確認するにはgit status
を使う。このコマンドによって、ワークツリーとステージの間で変更されたファイルと、ステージとリポジトリの間で変更されたファイルを確認する。
git status
ファイルの状態
- 追跡されているかどうか → 新規作成ファイル
- 未修正 → 追跡されていて前回のコミットから変更がない
- 修正済 → 追跡されていて前回のコミットから変更がある
- ステージ済 → ステージに変更が追加されている
コマンドにエイリアスをつける
エイリアスとはコマンドを省略して入力できるようにしたもの。
// PC全体でエイリアスを設定する
git config --global alias.[エイリアス] [gitのコマンド]
// 例
git config --global alias.ci commit
git config --global alias.st status
バージョン管理しないファイルを無視する
パスワードや設定、ログなど外部に公開したくないファイルはGitの管理から外す。
Git管理から外すには.gitディレクトリがあるディレクトリで.gitignoreファイルを作成し、Gitの管理から外したいファイルやディレクトリのパスと名前を記述する。
ローカルリポジトリを削除する
ローカルリポジトリを削除するには.git
を削除する。
rm -rf .git
Github
リモートリポジトリを確認する
リモートリポジトリを確認するにはgit remote
を使う。
// リモート名が表示される
git remote
// リモートのURLが表示される
git remote -v
リモートリポジトリを追加する
リモートリポジトリを追加するにはgit remote add
を使う。
リモートリポジトリはチーム開発とは別で個人のリポジトリをもっておきたいときなど複数登録できる。
git remote add [リモート名] [リモートURL]
リモート名にはorigin
という名前がよく使われる。これはGitがデフォルトで指定しているリモートリポジトリの名前である。
リモート名を指定することでリモートリポジトリに対して操作するときにURLを指定する必要がなくなる。
リモートリポジトリから情報を取得する
リモートリポジトリから情報を取得するにはクローン、フェッチ、プルの3つの方法がある。
クローン
クローンは最初だけリモートリポジトリの内容をローカルに取得するときに使う。フェッチとプルは都度情報を取得するときに使うもの。
git clone [リモートリポジトリのURL]
フェッチ
フェッチを行うとリモートリポジトリから情報を取得し、ローカルリポジトリの追跡ブランチに保存される。フェッチするにはgit fetch
を使う。取得した情報はワークツリーには反映されないので、反映したいときはgit merge
を使ってマージする。
git fetch [リモート名]
プル
プルを使うと、フェッチ→マージの2つのコマンドを1つで行うことができる。
git pull [リモート名] [ブランチ名]
フェッチとプルの使い分け
基本的にはフェッチを使う。プルを使うと、今いるブランチに取得した情報がマージされるので注意する。
フェッチ → リモートから情報を取得するだけ
プル → リモートから情報を取得し、ワークツリーに反映する(fetch + merge)
リモートリポジトリの詳細情報を表示する
リモートリポジトリの詳しい情報を知りたいときはgit remote show
を使う。
git remote show [リモート名]
表示される詳細情報
- fetchとpushのURL
- リモートブランチ
- git pullの挙動
- git pushの挙動
リモートリポジトリを変更する
リモートリポジトリを変更するにはgit remote rename
を使う。
git remote rename [旧リモート名] [新リモート名]
リモートリポジトリを削除する
リモートリポジトリを削除するにはgit remote rm
を使う。
git remote rm [リモート名]
ブランチとマージ
ブランチとは
ブランチとは、並行して複数の機能を開発するための仕組み。ブランチを使うことで他の人の変更の影響を受けなくなる。
ブランチの種類
ブランチには3つの種類がある。
ローカルブランチ
ローカルブランチはローカルで作成するブランチ。ローカルリポジトリを作成したときには自動的にローカルにmain(master)ブランチが作成されている。
リモートブランチ
リモートブランチはリモートに存在するブランチ。リモートブランチを作成するにはgit push
で行う。
git push -u [リモート名] [ブランチ名]
追跡ブランチ
追跡ブランチはリモートブランチを追跡するブランチのこと。追跡ブランチはリモートではなくローカルにある。
git branch -a
で表示されるremote/[リモート名]/[ブランチ名]
が追跡ブランチのこと。
git fetch
を行ったときに、リモートブランチの内容で追跡ブランチの内容を更新する。
git pull
だと追跡ブランチを今いるブランチにマージするところまで行われる。
リモートブランチの内容で更新された追跡ブランチをマージすることによってリモートブランチの内容をワークツリーに反映することができる。
ブランチの仕組み
ブランチは最新のコミットを指し示す参照である。
ブランチにはブランチ名をもつファイルがあり、その中にブランチごとの最新のコミットファイル名が記載されている。
ブランチの仕組みを理解するためには、コミットの仕組みとHEADを理解する必要がある。
コミットの仕組み
コミットは直前のコミットの情報を持っており、それによって履歴を辿ることができる。
ブランチは新しくコミットを行うとそのコミットを指し示すようになる。
HEAD
HEADは今自分が作業しているブランチを指し示す。他のブランチで作業したい時にはこのHEADを移動させることでブランチを切り替える。
HEADの中身は、今作業しているブランチの名前が記載されている。
HEADを移動させるとブランチが切り替わり、そのブランチでコミットを行うことで開発が分岐されていく。
ブランチを切る
新しいブランチを作成することをブランチを切るといい、git branch
を使う。git branch
はブランチを作成するだけでブランチの切り替えは行わないので、HEADは元々いたブランチを指している状態のままである。
// ブランチを作成する
git branch [ブランチ名]
// ブランチ名を入力しないとブランチの一覧を表示する
git branch
// 追跡ブランチも合わせて表示する
git branch -a
最初のコミットを行うとmaster
という名前のブランチが作成される。
最近はmaster
ではなくmain
という名前が使われる。
ブランチを切り替える
ブランチを切り替えるにはgit checkout
を使う。ブランチを切り替えるとHEADが切り替えたブランチを指すようになる。これによって別々の機能を並行して作ることができるようになる。
git checkout [ブランチ名]
// ブランチを作成し、そのブランチに切り替える
git checkout -b [ブランチ名]
ブランチ名を変更する
ブランチ名を変更するにはgit branch -m
を使う。
// 今作業しているブランチ名を変更する
git branch -m [ブランチ名]
ブランチを削除する
ブランチを削除するにはgit branch -d
を使う。
// マージされていないブランチは削除できない
git branch -d [ブランチ名]
// 強制削除する
git branch -D [ブランチ名]
変更をマージする
マージとは、他の人の変更内容を自分が今いるブランチに取り込むこと。マージを行うと2つのブランチを統合した新しいコミットが作成される。
マージするにはgit merge
を使う。
git merge [ブランチ名]
git merge [リモート名/ブランチ名]
マージには3種類ある。
- ファストフォワード
- オートマージ
- コンフリクト
ファストフォワード
片方のブランチはコミットを行い、もう片方のブランチがコミットをしていない(ブランチが分岐していない)ときにマージすること。このときブランチは最新のコミットのほうに参照を進める。
オートマージ
基本のマージ。別々のブランチでコミットを行い、それらのブランチをマージすること。このときマージコミットが作成される。マージコミットは2つの親コミットを持つ。
コンフリクト
コンフリクトとは、同じ箇所の異なる変更をマージした時にGitがどっちの変更を優先していいかわからない状態のこと。
コンフリクトが起きている状態でgit status
を実行すると、both modified
と表示される。
コンフリクトを解決するには、最終的なファイルの内容に書き換えること。
コンフリクトを起こさないように複数人が同じ箇所を変更しないように気をつける。
Githubを利用した開発手順の流れ
プルリクエスト
プルリクエストとは、自分が変更したコードをリポジトリに取り込んでもらうよう他の開発メンバーに依頼する機能のこと。コードを取り込む前に、バグを防いだり、コードの質を担保するためのレビューを行う必要がある。そのレビューを依頼するのがプルリクエスト。
プルリクエストは以下の手順で行う。
- ローカルのmainブランチを最新に更新する
- ローカルブランチを作成する
- ファイルを変更する
- 変更をコミットする
- Githubへプッシュする
- プルリクエストを送る
- プルリクエストを受けた人がレビューを行う
- レビューがOKであればプルリクエストをGithubのmainブランチにマージする
- マージが終わればリモートブランチを削除する
- ローカルブランチも削除する
Github Flow
Github Flowとは、Githubを利用した開発の方法の1つ。mainブランチから開発用のブランチを作成し、新しい機能の開発は開発用のブランチで行うためとてもシンプル。
Github Flowは以下の流れで開発する。
- mainブランチから開発ブランチを作成
- ファイルを変更し、コミットする
- Githubに変更をプッシュする
- プルリクエストを送る
- 承認されればmainブランチにマージする
- mainブランチを本番環境にデプロイする
mainブランチは常にデプロイできる状態を保ち、開発用のブランチは他の開発者が開発状況を把握できるようにするため定期的にプッシュすることが重要。
リベース
リベースとは、ブランチを統合する
git rebase [ブランチ名]
リベースとマージの違い
コミットの履歴を綺麗にしたいならリベースを使い、コミットの履歴を残したいならマージを使う。
リベースとプル
プルする時にもマージとリベースの違いがある。
// マージコミットが残る
git pull [リモート名] [ブランチ名]
// マージコミットが残らない
git pull --rebase [リモート名] [ブランチ名]
リベースの注意点
Githubにプッシュしたコミットをリベースしてはいけない。
タグ
タグとはコミットを参照しやすくするために名前をつけること。いつリリースしたかやどのバージョンかを示すためにつけられることが多い。
タグの一覧を表示する
タグの一覧を表示するためにはgit tag
を使う。
git tag
タグを作成する
タグを作成するにはgit tag
にタグ名をつける。タグには軽量版タグと注釈付きタグの2種類ある。
軽量版タグはタグの名前だけをつける。
注釈付きタグにはタグをつけた人の名前やコメントをつけることができる。
// 軽量版タグを作成する
git tag [タグ名]
// 注釈付きタグを作成する
git tag -a [タグ名] -m [メッセージ]
// 後からタグをつける
git tag [タグ名] [コミット名]
タグの詳細情報を確認する
タグの詳細情報を確認するにはgit show
にタグ名を使う。これによってタグをつけた人の情報、タグをつけた日時、注釈メッセージ、コミットの情報を確認することができる。
git show [タグ名]
タグをリモートリポジトリに送信する
タグをリモートリポジトリに送信するにはgit push
を使って別途で指定する。
// 任意のタグをリモートに送信
git push [リモート名] [タグ名]
// 全てのタグをリモートに送信
git push [リモート名] --tags
スタッシュ
スタッシュとは、作業の途中でコミットしたくない時に別のブランチに移動するために作業を一時避難すること。
作業を一時避難する
スタッシュするにはgit stash
を使う。変更分をstashに保存することで、変更を無かったことにする。
git stash
避難した作業を確認する
避難した作業を確認するにはgit stash list
を使う。
git stash list
避難した作業を復元する
避難した作業を復元するにはgit stash apply
を使う。
// 最新の作業を復元する
git stash apply
// 特定の作業を復元する
git stash apply [スタッシュ名]
// ステージの状況も復元する
git stash apply --index
避難した作業を削除する
避難した作業を削除するにはgit stash drop
を使う。
// 特定のスタッシュを削除する
git stash drop [スタッシュ名]
// 全てのスタッシュを削除する
git stash clear
まとめ
- Gitはバージョン管理を行うためのツール
- Gitは変更を差分ではなくスナップショットで保存し、そのスナップショットを辿ることで履歴を管理したり、ブランチを作成したりすることができる
- 変更を保存するにはステージに追加してコミットする
- Githubに変更を保存するにはローカルリポジトリにコミットしたものをプッシュする
- Githubからデータを取得するにはフェッチとプルの2つの方法があり、フェッチは取得するだけでマージせず、プルは取得してマージも行う
- 並行して別々の機能を作りたいときはブランチを作って分岐する
- ブランチは最新のコミットを指す参照である
参考
https://github.com/kaityo256/github/blob/main/internals/README.md
Git: もう怖くないGit!チーム開発で必要なGitを完全マスター
https://www.r-staffing.co.jp/engineer/archive/category/%E3%83%9E%E3%83%B3%E3%82%AC%E3%83%BBGit