個人でとりあえず使用する git コマンドまとめ

<font color="#ff8080">※2022/05/17: 記事を全体的に編集、一部内容の変更および追加しました。</font>

Git は複数人開発においても便利なツールですが、個人やローカル環境で使用しても便利です。
本記事は個人でとりあえず Git を使用する場合に最低限必要そうな内容をまとめてみました。

なるべく全体像が分かりやすいようにしたかったため、各項目の説明が要約や早見のようになっています。それぞれの詳しい使い方等は各自で調べてください。

# 1. 準備

## 1.1. SSH キーの設定 (GitHub 等のリモートリポジトリを使用する場合)

SSH キーの生成やログインの自動化に関しては色々な方法があるため、本記事では詳しく触れません。

いくつか参考記事を以下に載せますが、SSH を扱う方法はこれらに限られません。

参考「[新しい SSH キーを生成して ssh-agent に追加する - GitHub Docs](https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)」
参考「[GitHub アカウントへの新しい SSH キーの追加 - GitHub Docs](https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)」

## 1.2. Git の初期設定

- ユーザー設定
    - 名前
    - メールアドレス
- 新規リポジトリ作成時の初期設定ブランチ名: `main`
- 早送りマージ (Fast-Forward Merge) 設定
    - `git merge` するとき: `false` (常に追加でマージコミットを作成する)
    - `git pull` するとき: `only` (早送りマージできるならマージする。追加でマージコミットを作成しない)

```shell:コマンドで設定する場合
git config --global user.name '名前'
git config --global user.email 'メールアドレス'

git config --global init.defaultBranch main

git config --global merge.ff false
git config --global pull.ff only
```

```:~/.gitconfig&nbsp;を編集して設定する場合
[user]
	name = 名前
	email = メールアドレス
[init]
	defaultBranch = main
[merge]
	ff = false
[pull]
	ff = only
```

参考「[Variables - git-config Documentation - Git](https://git-scm.com/docs/git-config.html#_variables)」

ちなみに GitHub では、独自のプライベードメールアドレスを生成することで、自身の個人的なプライマリメールアドレスを非公開にすることができます。

参考「[コミットメールアドレスを設定する - GitHub Docs](https://docs.github.com/ja/account-and-profile/setting-up-and-managing-your-github-user-account/managing-email-preferences/setting-your-commit-email-address)」("Keep my email addresses private")

# 2. Git リポジトリの初期化

## 2.1. Git リポジトリの作成

Git リポジトリの作成はいくつかの方法があります。

- 先にリモートリポジトリ (GitHub 等) を作成し、後にローカルリポジトリ (自身の PC 上等) を作成する
- 先にローカルリポジトリ (自身の PC 上等) を作成し、後にリモートリポジトリ (GitHub 等) を作成する
    - またはローカルリポジトリのみ作成する

### 2.1.1. 先にリモートリポジトリを作成する場合

GitHub 等のリモートリポジトリを作成します。

リポジトリ作成時に README とライセンスファイルを生成するように設定すると良いです。

ライセンスにこだわりがない場合はとりあえず **MIT License** にすると楽です。

参考「[リポジトリを作成する - GitHub Docs](https://docs.github.com/ja/get-started/quickstart/create-a-repo)」

リモートリポジトリ作成後にローカルに `git clone` します。

```shell:先にリモートリポジトリを作成する場合
git clone <リポジトリ>

cd <ディレクトリ>

# グローバル設定と異なるユーザーでコミットしたい場合は以下を設定
# git config --local user.name '名前'
# git config --local user.email 'メールアドレス'
```

### 2.1.2. 先にローカルリポジトリを作成する場合

`git init` で空の Git ローカルリポジトリを作成します。

ファイルが既に存在するディレクトリで `git init` を実行しても大丈夫です。

```shell:先にローカルリポジトリを作成する場合
cd <ディレクトリ>

# git init 前にファイルを追加するのも可

git init

# グローバル設定と異なるユーザーでコミットしたい場合は以下を設定
# git config --local user.name '名前'
# git config --local user.email 'メールアドレス'

# README.md や LICENSE 等のファイルを追加
# 必要があれば .gitignore を追加

# 
git add -A # .gitignore が適切に設定されている前提
git commit -m 'first commit'

# リモートリポジトリと関連付ける
# ローカルで使用するだけなら以下は不要
git remote add origin <リポジトリ>
git push -u origin main # この後 git push は -u origin main 不要
```

※ .gitignore の書き方は本記事では触れません。

## 2.2. グローバル設定と異なるユーザーでコミットしたい場合

コミットに関するユーザーの情報は、名前とメールアドレスで管理されています。

グローバル設定 `--global` で名前とメールアドレスを設定するのと同様に、必要に応じてリポジトリごとに `--local` でユーザーの設定をすることができます。

```shell
git config --local user.name '名前'
git config --local user.email 'メールアドレス'
```

## 2.3. `develop` ブランチを作成

本記事の手順では最初に `main` ブランチが作成されます。
場合によりますが、基本的に `main` ブランチに直接コミットするのは避けるべきです。
今ある `main` ブランチの他に、`develop` ブランチを作成します。

```shell
git branch develop

# リモートリポジトリに反映する
# ローカルで使用するだけなら以下は不要
git push -u origin develop # この後 git push は -u origin develop 不要

# ※上記のコマンドでは develop ブランチに移動せず main ブランチのままであることに注意
# ※ git push はブランチを指定した場合は他のブランチからでも操作可能
```

※以前は `main` でなく `master` という名前が良く使用されていました。

参考「[The default branch for newly-created repositories is now main | GitHub Changelog](https://github.blog/changelog/2020-10-01-the-default-branch-for-newly-created-repositories-is-now-main/)」

※より多くのブランチを利用するブランチモデルもありますが、個人でとりあえず使用するとして本記事では `main` と `develop` だけブランチを使用することにします。

# 3. ブランチを切り替え

## 3.1. 基本

作業するブランチを切り替えます。

```shell:従来の手法
git checkout <ブランチ>
```

```shell:v2.23.0&nbsp;以降の実験的な代替手法
git switch <ブランチ>
```

## 3.2. ブランチを新規作成して同時に移動する場合

本記事の手順では利用しませんが、ブランチの作成と同時に移動することもできます。

```shell:従来の手法
git checkout -b <ブランチ>
```

```shell:v2.23.0&nbsp;以降の実験的な代替手法
git switch -c <ブランチ>
```

# 4. コミット

本記事の手順では、基本的に `develop` ブランチで作業します。

```shell:従来の手法
git checkout develop
```

```shell:v2.23.0&nbsp;以降の実験的な代替手法
git switch develop
```

## 4.1. 基本

```shell:新規追加ファイルを含む変更分のコミット
git add -A # .gitignore が適切に設定されている前提
git commit -m 'プレフィックス: メッセージ'
```

※ .gitignore の書き方は本記事では触れません。

```shell:新規追加ファイルを含まない変更分のコミット
git commit -am 'プレフィックス: メッセージ'
```

プレフィックスの例として、以下のようなものがあります:

- `fix`：バグ修正
- `add`：新規機能・ファイル追加
- `update`：バグ修正以外の変更
- `remove`：機能・ファイルの削除

参考「[Gitのコミットメッセージの書き方 - Qiita](https://qiita.com/itosho/items/9565c6ad2ffc24c09364)」

※個人で使用する分にはプレフィックスが少なくても良いかと思いますが、複数人開発等の場合にはプレフィックスの数を多くしないとコミットメッセージが他人に伝わりにくいことがあります。
※より本格的な使い方ではコミットメッセージを複数行にしてタイトルと本文に分けますが、個人でとりあえず使用する分には 1 行で要約を書くだけでも良いと思います。

## 4.2. コミットメッセージで Issue を閉じる (GitHub 等を使用する場合)

GitHub 等で Issue を閉じたいときは、コミットメッセージに `Closes #<Issue 番号>` 等の記述を含め、デフォルトブランチにマージすることで閉じることができます。

詳しくは下記のドキュメント等をご参照ください。

参考「[キーワードを使用してPull RequestをIssueにリンクする - Pull RequestをIssueにリンクする - GitHub Docs](https://docs.github.com/ja/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)」(Pull Request でなくコミットメッセージでも利用可能)

※本記事では Pull Request の説明はしないため、単にコミットメッセージで利用する想定です。

## 4.3. その他

少し特別な例として、以下のようなコマンドも便利です。

```shell:直前のコミットに変更を付け足す
git add -A # .gitignore が適切に設定されている前提
git commit --amend --no-edit
```

※ .gitignore の書き方は本記事では触れません。

```shell:直前のコミットメッセージを変更する
git commit --amend -m 'プレフィックス: メッセージ'
```

`develop` ブランチでコミットしたかったのを間違えて `main` でしてしまった場合等は、`git cherry-pick` を使用してコミットを別のブランチに移動できます。

```shell:コミットを現在のブランチに移動する
git cherry-pick <コミットハッシュ値>
```

※コミットハッシュ値は最大 40 文字ですが、コミットが特定できればハッシュ値の先頭の部分だけで指定できます (`git cherry-pick` に限りません) 。
※コミットハッシュ値の短縮形として先頭 7 文字が使われることが多いです。

# 5. マージ

マージは、他のブランチから変更分を持ってきて統合する処理です。

## 5.1. 基本

「統合する」という認識だけだとどちらがどちらのブランチか分かりにくいですが、「変更をもらう」と考えると分かりやすいです。

変更分を `<from ブランチ>` から `<to ブランチ>` に持っていきたいとき、`<to ブランチ>` に checkout した後、`<from ブランチ>` から `git merge` で変更分をもらいます。

```shell:&amp;lt;from ブランチ&amp;gt; から変更分をもらう
git checkout <to ブランチ>
git merge --no-edit <from ブランチ>
```

※本記事では `merge.ff = false` の設定をしていることを前提としていますが、その設定をしていない場合には `--no-ff` オプションを使用することでマージコミットの作成を強制できます。
※本格的な使い方では `--no-edit` にせずコミットメッセージを書いた方が良いですが、個人でとりあえず使う分には書かなくても良いかと思います。

`main` ブランチと `develop` ブランチの構成で運用する場合、`develop` で開発を進めた後に `develop` から `main` にマージすることになります。

## 5.2. コンフリクトが起きたとき

個人で `main`, `develop` ブランチのみを使用している場合はあまりコンフリクトは起きませんが、ブランチがもっと多くなったり複数のブランチで同時進行で作業したりした場合にはコンフリクトが起きる可能性があります。

コンフリクトを解決し、新たにコミットしすると解決できます。

```shell:コンフリクトを解決した後にマージコミット
git commit -a --no-edit
```

※ `git add` にするか `git commit -a` にするかは通常のコミットと同様。
※ `--no-edit` にするかどうかは `git merge` と同様。

コングリクトを解決する具体的な方法は色々あるため、本記事では深く触れません。

一例として、以下コマンドでどちらかのブランチの変更分を選択できます。

```shell:従来の手法
# 現在のブランチのファイルを選択する場合
git checkout --ours <ファイル名>

# 相手のブランチのファイルを選択する場合
git checkout --theirs <ファイル名>
```

```shell:v2.23.0&nbsp;以降の実験的な代替手法
# 現在のブランチのファイルを選択する場合
git restore --ours <ファイル名>

# 相手のブランチのファイルを選択する場合
git restore --theirs <ファイル名>
```

# 6. プッシュ (GitHub 等のリモートリポジトリを使用する場合)

ローカルリポジトリからリモートリポジトリに変更分を反映させます。

(ローカルリポジトリのみで使用する場合には不要。)

## 6.1. 基本

Git では基本的にリポジトリごとでなくブランチごとに変更分を反映させます。

※ `push.default` という項目の設定で挙動を変更できます。古いバージョンの Git では標準の挙動が異なりました。

```shell:ブランチを反映
git push
```

タグ (後述) を使用している場合には、上記だけだと反映されないので、以下も実行します。

```shell:タグを反映
git push origin <タグ名>
```

## 6.2. 特別な例: 過去改変したいとき

特別な例として、ローカルリポジトリで過去改変を行った場合は、以下のコマンドでリモートに反映させることができます。

```shell:過去改変等をしたときに強制&nbsp;push
git push -f
```

原則としては使用しない方が良いです。

# 7. タグ

## 7.1. 基本

Git では、コミットに対してタグを付けることができます。

Git のタグは、複数のコミットに同じタグを付けることはできず、ある 1 つのコミットに 1 つのタグを付けることができます。

何らかの重要なコミットに別名を付けるような機能です。

```shell:直近のコミットに軽量版タグを付ける
git tag <タグ名>
```

※ Git のタグは他にも様々な高度な付け方がありますが、本記事では一番簡単な「軽量版タグ」のみ記載しています。

## 7.2. タグでバージョン番号を表す

Git のタグは主に、`main` ブランチのコミットに `v1.0.0` のようなバージョンタグを付けるのに使用します。

バージョン番号は「**セマンティック バージョニング**」に従うようにすると良いです:

- 基本は `x.y.z` の形
- 開発開始時は `0.1.0`
- `x` を上げるのは互換性のない変更をしたとき
    - ただし開発初期は `x` は `0` のままで `y` を上げる
- `y` を上げるのは互換性のある機能追加をしたとき
- `z` を上げるのは互換性のあるバグ修正をしたとき

参考「[セマンティック バージョニング 2.0.0 | Semantic Versioning](https://semver.org/lang/ja/)」

Git のタグとしてはバージョン番号の先頭に単に "v" を付けたものが広く使われているため、その方法で統一した方が良いです。

例: バージョン番号 `1.0.0` のときタグ名 `v1.0.0`

ちなみに GitHub では、タグを付けたコミットが Releases の一覧に表示されます。

# 8. 色々な情報を見る

Git の情報を見るコマンドの例:

- `git status`: 現在の状態を見る
- `git diff`: 差分を見る (`git add` されていない差分)
    - `git diff --cached`: 差分を見る (`git add` されているが `git commit` されていない差分)
    - オプション `-U<n>`: 差分の上下 n 行も表示する (`-U0` なら差分の行のみ表示)
    - オプション `--word-diff-regex=.`: 文字単位差分を見る (ちなみに `--word-diff` のみはスペース区切りの単語単位の差分)
- `git log`: コミットのログを見る

それぞれもっと多くの機能がありますが、本記事では主要と思うもののみ記載。

# 9. リモートリポジトリからローカルリポジトリに変更を反映させたい場合

ローカルのみで Git を使用する場合や個人で単一の PC で Git を使用し一方的にプッシュするだけなら不要ですが、リモートリポジトリの内容が他から変更された場合はローカルに反映する必要があります。

- `git fetch`: リモートの変更を取得するがローカルの内容にマージしない
- `git pull`: リモートの変更を取得してローカルの内容にマージする
    - `git pull --rebase`: リモートの変更を取得してローカルの内容をリベースする

※マージとリベースの違いを理解するにはより多くの説明が必要になるため、本記事では説明しません。
※多くの場合はリベースよりマージの方が好ましいですが、`git pull` に関してはリベースの方が良いという意見があります。
※ `git pull` は `git merge` 等と同様にコンフリクトが発生する可能性がありますが、解決方法は色々あるため、本記事では触れません。

# 10. とりあえず使う運用

以下を繰り返します:

1. `develop` ブランチ
    1. ブランチ移動
    1. (必要に応じて pull 等)
    1. add, commit
    1. push
1. `main` ブランチ
    1. ブランチ移動
    1. (必要に応じて pull 等)
    1. `develop` の変更内容を merge
    1. 必要に応じて tag 設定
    1. push
    1. タグ push

(`main` から `develop` に戻り忘れたら cherry-pick 。)

ちなみに、大人数で開発する場合等ではより多くのブランチを用いるブランチモデルで開発した方が良いですが、各ブランチモデルごとに長所と短所があり、どれかが一番良いということはありません。
「Git Flow ブランチモデル」は有名ですが、少人数での開発やリリースの頻度が高いプロジェクト向きではないという意見があります。

# 11. その他

- `git rebase`: `git merge` の代わりに使われることもあるが、普段はあまり使わない方が良い
- `git stash`: 作業を一時的に退避
- `git reflog`: リポジトリ内の操作履歴。Git で誤った操作をしてしまったときに復元するとき等で使用
- `git reset`: 変更を元に戻す
- `HEAD` や `^` 等を用いたコミットの指定
- ファイルの移動は `git mv` 、または普通の `mv` でも追跡可能
- .gitattributes による Linguist 等の設定
- プルリクエスト
- 複数人の場合に GitHub 等で `main` をいじられないようにする設定等

参考「[Git - Revision Selection](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection)」

他にも様々な機能があります。各自で確認してみてください。