🎈

Git基礎学習

2023/05/03に公開

自分の理解のため、普段使っているgitについてまとめました。

1. gitを使い始める準備

1.1. インストール

代表的な方法を記載する。
いくつかインストール方法があるので git 公式のダウンロードページを参照

  • Windows
    Git for Windows のインストーラーをダウンロードして実行

  • Mac

    gitインストール(Mac)
    brew install git
    
  • Linux (Ubuntu)

    gitインストール(Linux)
    apt-get install git
    

筆者環境は macOS Ventura, git v2.39.2

環境
sw_vers
ProductName:     macOS
ProductVersion:  13.3.1
BuildVersion:    22E261

git --version
git version 2.39.2

1.2. config

1.2.1. グローバル設定

author/committer 情報
# 誰がコミットしたか、git log などに載る
git config --global user.name "<ユーザー名>"
git config --global user.email "<メールアドレス>"
git 管理から除外するファイル設定
# グローバル設定には、PCやよく使うIDE等、リポジトリに依存しない共通の除外設定を入れる
# ignore ファイルの内容は、以下の設定など参考
# https://github.com/github/gitignore/blob/main/Global/macOS.gitignore
touch ~/.gitignore_global
コマンド別名
# よく使うコマンドは短いエイリアスを付けておくと便利 git <エイリアス名> で実行可能
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
# コミット履歴フォーマット指定
git config --global alias.logp "log --pretty=format:'%h 🕒%cd 🙋%an %s' --date=format:'%Y-%m-%d %H:%M'"
# コミット履歴をグラフ表示
git config --global alias.graph "log --oneline --decorate --graph --branches --tags --remotes --all"

1.2.2. ローカル(リポジトリ毎の)設定

author/committer 情報
# 誰がコミットしたか、git log などに載る
git config --local user.name "<ユーザー名>"
git config --local user.email "<メールアドレス>"
git 管理から除外するファイル設定
# ローカル設定には、プログラミング言語やランタイム、対象の開発で使うIDE等の除外設定を入れる
# ignore ファイルの内容は、以下の設定など参考
# https://github.com/github/gitignore/blob/main/Android.gitignore
# https://github.com/github/gitignore/blob/main/Java.gitignore
touch .gitignore

1.3. リポジトリ用意

1.3.1. リモートリポジトリから作る場合

GitHub / GitLab / Bitbucket などのホスティングサービスでリポジトリを作り、それを利用する場合

リポジトリを複製
git clone <リモートリポジトリURL>
メインブランチを作成
git branch -M main
初期コミット作成
# --allow-empty は空コミットを作る場合のみ必要
# 初期コミットで README.md など何かファイルを作る場合は不要
git commit -m "initial commit" [--allow-empty]
初期コミットをリモートに送信
git push

すでにコミットが入っている状態のリポジトリからクローンするのみの場合は以下

クローン
git clone [-b <ブランチ名>] <リモートリポジトリURL> <クローン先ローカルディレクトリ>

1.3.2. 既存のローカルリポジトリをリモートにアップロードする場合

予めローカルで作成したリポジトリを GitHub / GitLab / Bitbucket などのホスティングサービスで作った直後のリポジトリと連携する場合

ローカルリポジトリを準備
mkdir <プロジェクト名>
cd <プロジェクト名>
git init -b main
初期コミット作成
# --allow-empty は空コミットを作る場合のみ必要
# 初期コミットで README.md など何かファイルを作る場合は不要
git commit -m "initial commit" [--allow-empty]
リモートリポジトリを関連付け
# (GitHub httpsの例) git remote add origin https://github.com/{ユーザーID}/{リポジトリ名}.git
# (GitHub sshの例)   git remote add origin git@github.com:{ユーザーID}/{リポジトリ名}.git
git remote add origin <リモートリポジトリURL>
初期コミットをリモートに送信
git push -u origin main

2. 編集ワークフロー

2.1. コミット状態遷移

edit-workflow
コミット状態遷移

コミット・ブランチ図示凡例
コミット・ブランチ図示凡例

2.1.1. コミットフロー

指定ファイルをIndexに追加
git add <ファイル名/ディレクトリ名>...
コミット
# -m を付けない場合はエディターが起動してメッセージを入力する
git commit -m "<メッセージ>"

コミット

プッシュ
git push [リモート名: e.g. origin] [<ブランチ名>]

プッシュ

2.1.2. 共有コミットからの同期フロー

フェッチ
git fetch [リモート名: e.g. origin] [<ブランチ名>]

リモートリポジトリからコミット、ファイル、ブランチ等のコミット参照オブジェクトなどをダウンロードする。

ただし、情報を反映するのはローカルリポジトリのリモートブランチまでで、ローカルブランチへは反映しない。
ローカルブランチまで反映したい場合は、リモートブランチからローカルブランチにマージする。

マージ
# カレントブランチを切り替えたのちマージ
git switch <ブランチ名>
git merge origin/<ブランチ名>
プル
git switch <ブランチ名>
git pull [リモート名: e.g. origin]

2.1.3. Working Directory の変更差分を一時的に退避する

pull などでリモートリポジトリの内容をローカルに取り込む際、途中まで変更していた差分があると pull が上手くいかないことがある。
そんな場合に、変更差分を一時退避して Working Directory の差分がない状態にできる。

Working Directory 変更差分一時退避
git stash [push [-u]] [<メッセージ>]

Saved working directory and index state WIP on <ブランチ名>: 533daa3 <コミットメッセージ>

一時退避した差分はストックできる。

現在、どんな stash があるか一覧表示で確認可能。

stash 一覧表示
git stash list

stash@{0}: WIP on <ブランチ名>: 533daa3 <コミットメッセージ>
stash@{1}: WIP on <ブランチ名>: 533daa3 <コミットメッセージ>

各 stash の内容を見たい場合は以下で可能。

stash 内容表示
git stash show stash@{0} -p

diff --git a/sample.txt b/sample.txt
index 422c2b7..de98044 100644
--- a/sample.txt
+++ b/sample.txt
@@ -1,2 +1,3 @@
 a
 b
+c

一時退避していた差分を適用し直すことができる。

stash を適用
git stash apply [stash@{n}]
stash を適用して stash 削除
git stash pop [stash@{n}]

不要になった stash は削除する。

git stash drop [stash@{n}]

2.1.4. 復元フロー

Index から復元
git restore --staged <ファイル名>...
Working Directory のファイル編集差分をリセット
git restore --worktree <ファイル名>...
コミット履歴を取り消して、その差分を Index に戻す
git reset --soft HEAD~<取り消すコミット数>
コミット履歴を取り消して、その差分を Working Directory まで戻す
git reset --mixed HEAD~<取り消すコミット数>
コミット履歴を取り消して、差分を完全に削除する
git reset --hard HEAD~<取り消すコミット数>

2.2. コミット状態の確認方法

2.2.1. Working Directory と Index の確認

状態の確認
git status

On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
 new file:   sample_01.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  modified:   sample_01.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
 sample_02.txt
  • Changes to be committed
    • Index の内容
  • Changes not staged for commit
    • Working Directory の変更 (git 管理済ファイル)
  • Untracked files
    • Working Directory の変更 (git 未管理ファイル)

2.2.2. コミット履歴の確認

コミット履歴表示基本
# 最新何件かのみで良い場合は -n オプション
git log
commit 7cdaa2a180ded54dc0281a7d914f10f1e3a7e999 (HEAD -> main)
Author: {ユーザー名} <{メールアドレス}>
Date:   Mon May 1 15:46:56 2023 +0900

    {コミットメッセージ}

commit 5bafb2479fa185c731f32d4180383c29da6ab2e8 (origin/main)
Author: {ユーザー名} <{メールアドレス}>
Date:   Mon May 1 15:46:56 2023 +0900

    {コミットメッセージ}
1行表示
git log --oneline
7cdaa2a (HEAD -> main, origin/main) {コミットメッセージ}
5bafb24 {コミットメッセージ}
簡易表示
git log --pretty=short
commit 7cdaa2a180ded54dc0281a7d914f10f1e3a7e999 (HEAD -> main, origin/main)
Author: {ユーザー名} <{メールアドレス}>

    {コミットメッセージ}
フォーマット詳細指定表示
git log --pretty=format:'%h 🕒%cd 🙋%an %s' --date=format:'%Y-%m-%d %H:%M'

<コミットIDハッシュ> 🕒<コミット日時> 🙋<author名> <コミットメッセージ>
140866c 🕒2023-05-03 00:28 🙋<author名> <コミットメッセージ>
c32e3ca 🕒2023-05-02 20:45 🙋<author名> <コミットメッセージ>
グラフ表示
git log --decorate --graph --all --oneline
* a04497e (HEAD -> feature/test01) change sample_02
| *   bb7624d (refs/stash) WIP on feature/test01: 533daa3 change sample_02
| |\
| | * b7052bf index on feature/test01: 533daa3 change sample_02
| |/
| * 533daa3 change sample_02
|/
* 0ce5883 (origin/main, origin/feature/test01, main) change sample_01
* 7cdaa2a add sample files 01-02
* 5bafb24 🎉 initial commit

2.2.3. ローカル差分の確認

未ステージの Working Directory の差分
git diff

diff --git a/sample_01.txt b/sample_01.txt
index 422c2b7..de98044 100644
--- a/sample_01.txt
+++ b/sample_01.txt
@@ -1,2 +1,3 @@
 a
 b
+c
diff --git a/sample_02.txt b/sample_02.txt
index 7898192..422c2b7 100644
--- a/sample_02.txt
+++ b/sample_02.txt
@@ -1 +1,2 @@
 a
+b
未ステージの Working Directory の差分(パス指定)
git diff sample_02.txt

diff --git a/sample_02.txt b/sample_02.txt
index 7898192..422c2b7 100644
--- a/sample_02.txt
+++ b/sample_02.txt
@@ -1 +1,2 @@
 a
+b
ステージ済の差分
git add sample_02.txt
git diff --staged

diff --git a/sample_02.txt b/sample_02.txt
index 7898192..422c2b7 100644
--- a/sample_02.txt
+++ b/sample_02.txt
@@ -1 +1,2 @@
 a
+b

2.2.4. コミット差分の確認

コミット間の差分
# git diff <fromコミット> <toコミット>
git diff HEAD~2..HEAD~1

diff --git a/sample_01.txt b/sample_01.txt
new file mode 100644
index 0000000..7898192
--- /dev/null
+++ b/sample_01.txt
@@ -0,0 +1 @@
+a
diff --git a/sample_02.txt b/sample_02.txt
new file mode 100644
index 0000000..7898192
--- /dev/null
+++ b/sample_02.txt
@@ -0,0 +1 @@
+a
対象コミットでの差分
git show HEAD
commit 0ce5883c412d04e9837852ae6c57d42abbe215e0 (HEAD -> main, origin/main)
Author: {ユーザー名} <{メールアドレス}>
Date:   Mon May 1 16:58:14 2023 +0900

    change sample_01

diff --git a/sample_01.txt b/sample_01.txt
index 7898192..422c2b7 100644
--- a/sample_01.txt
+++ b/sample_01.txt
@@ -1 +1,2 @@
 a
+b

2.2.5. ファイル内の各行を最後に変更したコミット表示

ファイル内の各行最終変更コミット
git blame sample_01.txt

7cdaa2a1 ({ユーザー名}        2023-05-01 15:46:56 +0900 1) a
0ce5883c ({ユーザー名}        2023-05-01 16:58:14 +0900 2) b
00000000 (Not Committed Yet 2023-05-03 17:11:50 +0900 3) c

2.3. ブランチ操作

ブランチは、コミットの履歴を分岐してある目的の修正を他の修正の影響を受けずに開発していくための機能です。
mainブランチ1本でも開発は一応可能ですが、いろんな差分が1本の履歴に入っているとデメリットが多いです。

  • 並行作業しにくい
  • ある機能を開発している途中に別機能の改造も入ってきて、影響を受けやすい
  • 関連する改造が分かりにくく、レビューしにくい

上記は一例ですが、これだけを見てもチーム開発では(個人開発でも)ある程度目的別にコミットを分離することが必要であるとわかります。

2.3.1. ブランチ作成

HEAD位置にブランチ作成
git branch <ブランチ名> 

ブランチ作成

指定位置にブランチ作成
git branch <ブランチ名> <ブランチ作成位置:ブランチ名、タグ名、コミットIDなど>

ブランチ作成

2.3.2. ブランチ一覧

ブランチ一覧表示(ローカル)
git branch
  feature/user-list
* main
ブランチ一覧表示(リモート)
git branch -r
  origin/main
ブランチ一覧表示(ローカル+リモート)
git branch -a
  feature/user-list
* main
  remotes/origin/main

2.3.3. リモート追跡ブランチ設定(既存リモートブランチなし)

リモート追跡ブランチ設定
# git push -u <リモートリポジトリ名> <ブランチ名>
git push -u origin feature/user-list

リモート追跡ブランチ作成

実行前後のブランチ表示
# 実行前
git branch -a
  feature/user-list
* main
  remotes/origin/main

# 実行後
git branch -a
  feature/user-list
* main
  remotes/origin/feature/user-list (※リモートに feature/user-list が追加された)
  remotes/origin/main

2.3.4. リモート追跡ブランチ設定(既存リモートブランチあり)

リモート追跡ブランチ設定
# git branch -u <リモートブランチ名> <ブランチ名>
git branch -u origin/feature/user-list feature/user-list

2.3.5. カレントブランチ変更(既存ブランチ)

checkout または switch を使用する。

カレントブランチ変更
git checkout <ブランチ名>
git switch <ブランチ名>

カレントブランチ変更

2.3.6. カレントブランチ変更(新規ブランチ)

既存でブランチが存在しない場合に、カレントブランチ変更と共にブランチを新規作成する。

ブランチ新規作成+カレントブランチ変更
git checkout -b <ブランチ名>
git switch -c <ブランチ名>

2.3.7. ブランチ削除

ローカルブランチ削除
git branch -d <ブランチ名>

ブランチ削除

カレントブランチは削除不可。

指定したブランチがマージされていない場合などに -d ではエラーとなる。
問題ない場合は -D で強制的に削除することができる。

ローカルブランチ強制削除
git branch -D <ブランチ名>
リモートブランチ削除
git push --delete origin <ブランチ名>

2.3.8. ブランチ名変更

ローカルブランチ名変更
git branch -m <oldブランチ名> <newブランチ名>

ブランチ名変更

存在するブランチ名へ変更する際は -M で強制する。
既存ブランチが別のコミットを指していた場合は、参照先がoldブランチの参照先に変更となる。

ローカルブランチ名強制変更
git branch -M <oldブランチ名> <newブランチ名>

リモートブランチ名の変更は、別名でブランチ作成して既存ブランチを削除する。

リモートブランチ名変更
git branch -m <oldブランチ名> <newブランチ名>
git push --delete origin <oldブランチ名>
git push -u origin <newブランチ名>

2.3.9. マージ

マージ
git switch <マージ先ブランチ名>
# カレントブランチに指定したブランチをマージする
git merge <マージ元ブランチ名/コミットID/タグなど>

マージ戦略として fast-forward, 3-way がある。

マージ戦略 説明
fast-forward マージ先がマージ元の親であり、ブランチ参照先を単純に変更するだけで行うマージ。
3-way マージ元とマージ先の両方を親とするマージコミットを作成し、マージ先の参照先をマージコミットに変更することで行うマージ。

fast-forward マージ
main に feature/user-list を マージして fast-forward となる場合

3-way マージ
main に feature/user-list を マージして 3-way となる場合

マージ戦略オプション 説明
--ff 可能であれば fast-forward でマージする。できない場合は 3-way でマージする。(デフォルト動作)
--no-ff fast-forward マージできる場合でもマージコミットを作って 3-way マージする。
--ff-only fast-forward マージできない場合はコマンドを失敗させる。

2.4. タグ操作

タグの種類 説明
軽量タグ コミットの単なる参照
注釈付きタグ タグ付けメッセージ、日付等のメタデータを持つタグ。リリースに際してタグを打つ場合にリリース情報を載せるなどの使い方ができる。

2.4.1. タグ作成

軽量タグ作成
# git tag <タグ名> [<コミット>]
git tag v1 HEAD~1
注釈付きタグ作成
# git tag <タグ名> [<コミット>] -a -m "<注釈メッセージ>"
git tag v2 -a -m "Version 2"
リモートにタグを作成
# git push origin <タグ名>
git push origin v1

2.4.2. タグ確認

タグ一覧
git tag -l
v1
v2

# ワイルドカードを使ったパターンで検索可能
git tag -l '*2'
v2
タグの詳細確認
git show v2
tag v2
Tagger: {ユーザー名} <{メールアドレス}>
Date:   Wed May 3 17:57:31 2023 +0900

Version 2

commit 0ce5883c412d04e9837852ae6c57d42abbe215e0 (tag: v2)
Author: {ユーザー名} <{メールアドレス}>
Date:   Mon May 1 16:58:14 2023 +0900

    change sample_01

diff --git a/sample_01.txt b/sample_01.txt
index 7898192..422c2b7 100644
--- a/sample_01.txt
+++ b/sample_01.txt
@@ -1 +1,2 @@
 a
+b

2.4.3. タグを削除

ローカルのタグ削除
# git tag -d <タグ名>
git tag -d v1
リモートリポジトリのタグ削除
git push --delete origin v1

3. まとめ

基本的な git コマンドを中心に図を交えてどんな操作ができるのかまとめてみた。
正直、GUIクライアントの方が操作が簡単だったり、状況が分かりやすかったりする部分も多いのだが、CLIでもある程度操作可能な方が安心して使えるだろう。
近いうちに rebase などのコミット履歴の操作についてもまとめたい。

4. さらに学習する

  • git 公式 Pro Git book
  • git 公式 コマンドリファレンス
  • Bitbucket チュートリアル
  • サル先生のGit入門〜バージョン管理を使いこなそう〜
  • GitHub Training Kit

以上

Discussion