git/githubコマンドチートシート(git/ghコマンド)[gitの概念を理解し，適切にコマンドを使おう]

この記事ではgit操作用のgitコマンドとgithub操作用のghコマンドのよく使うコマンドを記載する．

git操作は**GUIとCLIともに使える**と効率よく開発できる．
gitコマンドとghコマンドをマスターすることで，開発効率が大幅に向上する．コマンドラインから直接操作することで，バージョン管理やGitHub上の作業が迅速かつ正確に行えるようになるだろう．これにより，コードの変更追跡，チーム内でのコラボレーション，複雑な操作の実行が容易になる．
また，これらのコマンドは自動化やスクリプト作成に適しており，CI/CDパイプラインへの統合も簡単である．GUIツールに比べて高速で柔軟な操作が可能となり，リモート環境でも効率的に作業できる．



# 他のチートシート
lazygit

https://qiita.com/JavaLangRuntimeException/items/42087d09728d5739d73d

> git操作をターミナル(TUI)で行うことができる便利ツールです！ぜひ使ってみてきださい

SQL

https://qiita.com/JavaLangRuntimeException/items/f038fbaccdd92fb0308a

TypeScript

https://qiita.com/JavaLangRuntimeException/items/5894391c08e0d8e28389

Go/Gorm

https://qiita.com/JavaLangRuntimeException/items/d388717fc1436bc3ec9d


C#/.NET/Unity

https://qiita.com/JavaLangRuntimeException/items/7849b32bc223d4aa0247

Ruby・Ruby on Rails

https://qiita.com/JavaLangRuntimeException/items/42d935cf92c212f1c7ec

Docker コマンド

https://qiita.com/JavaLangRuntimeException/items/21f7c7bf3d143f821697

ステータスコード

https://qiita.com/JavaLangRuntimeException/items/ab1bc7b976ed2dfad91c

プルリクエスト・マークダウン記法チートシート

https://qiita.com/JavaLangRuntimeException/items/329eb92a47a07ff4dde8

ファイル操作コマンドチートシート

https://qiita.com/JavaLangRuntimeException/items/16f244606a73f7d106e4

Vim 

https://qiita.com/JavaLangRuntimeException/items/0c68ab96ea198e0a7294

VSCode Github Copilot拡張機能

https://qiita.com/JavaLangRuntimeException/items/be13dc3a346cf6e5ee44

OpenAI Assistants API

https://qiita.com/JavaLangRuntimeException/items/1a1abc01e8d7d05dce93

Github API

https://qiita.com/JavaLangRuntimeException/items/4f3551c31679233219ac

# 他のシリーズ記事
**TypeScriptで学ぶプログラミングの世界**
プログラミング言語を根本的に理解するシリーズです．

https://qiita.com/JavaLangRuntimeException/items/cadf49bb419076819963

**情報処理技術者試験合格への道[IP・SG・FE・AP]**
情報処理技術者試験の単語集です．

https://qiita.com/JavaLangRuntimeException/items/991be402099542ccb936

**IAM AWS User クラウドサービスをフル活用しよう！**
AWSのサービスを例にしてバックエンドとインフラ開発の手法を説明するシリーズです．

https://qiita.com/JavaLangRuntimeException/items/371a334f5a6e07035db5

**AWS UserのGCP浮気日記**
GCPの様子をAWSと比較して考えてみるシリーズ

https://qiita.com/JavaLangRuntimeException/items/527d99e774165a763180

**Project Gopher: Unlocking Go’s Secrets**
Go言語や標準ライブラリの深掘り調査レポートです．

https://qiita.com/JavaLangRuntimeException/items/dc45b412d3fbd2ccb9e8

**Gopher’s Journey: Exploring TCP Protocol**
Goを用いてTCPプロトコルを探求 & 作成するシリーズです．

https://qiita.com/JavaLangRuntimeException/items/38091220106d86651d2b



# gitの概念
まず初めのgitの概念と基本操作の説明をする．

# gitとは

Git は， **分散型バージョン管理システム（DVCS：Distributed version control system）** の一つであり、ソフトウェア開発におけるソースコードの変更を追跡および管理するために広く使用されている．個人の開発からオープンソースプロジェクト、大規模な商用プロジェクトまで、あらゆる規模のソフトウェア開発で使用されている．また、GitHubやBitbucketなどのホスティングサービスと連携することで、リモートリポジトリの管理やコラボレーションがより便利になる．

:::note info
**バージョン管理システム（VCS: Version Control System)とは**
ファイルやプロジェクトの変更履歴を記録，追跡，および管理するためのソフトウェアツール．
>まあ噛み砕いて言えば開発時に色々な機能を実装すると思うが，ある機能が実装できて，新しいバージョンにしたいとき，変更をしたバージョンでのソースコードを保存でき，いつでもそのバージョンに戻せたり，他の人と共同作業するときにデータに整合性を保つこと(つまり，保存された履歴や変更内容が改ざんされていないことを保証すること)ができるということ

:::




## git/githubを使うための基本用語
### リポジトリ
VCSにおいて，プロジェクトのファイルや変更履歴を保存する中央の保管場所を指す．リポジトリは，プロジェクトの全てのバージョンと，それらの間の差分を含んでいる．

:::note info
あるリポジトリにある`.gitディレクトリ`にリポジトリのメタデータと履歴が保存される．
:::

リポジトリには2種類あり,GitHubのようなリモート上にあるリポジトリとローカルにあるリポジトリで区別できる.

**リモートリポジトリ**
GitHubやGitLabなどのホスティングシステムのサーバー上に存在し,インターネットを介してアクセスできるため,チームメンバー全員がアクセスでき,変更を共有できる.

**ローカルリポジトリ**
開発者のコンピュータ上に存在し、直接アクセスできるため,開発者自身のみがアクセスできる.開発者が個々の作業を行い,変更をコミットして更新する.この変更をリモートリポジトリにプッシュして更新する.

### クローン（clone）
リモートリポジトリのコピーをローカルに作成する．

![スクリーンショット 2024-05-02 22.23.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/08203925-c3a6-ccdb-d670-9d133bf638b0.png)


### ブランチ(branch)

![スクリーンショット 2024-05-03 3.02.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/086eb08a-52bf-9c3a-9228-6577db61577a.png)
メインの開発ラインから独立して，**新機能の開発やバグ修正**などを行うために使用される機能．ブランチを使用することで，複数の開発者が同時に異なる作業を行うことができ，それらの変更を後でメインラインにマージすることができる．個人開発の時も機能を分割して整合性を高めるためにブランチを分けることをお勧めする．

上記の画像にもあるようにbranchの命名規則は基本的に **デフォルトブランチがmain/master** となり， **開発用のブランチとしてdevelop** で，　**各機能の作成用にfeature**がある．main/masterブランチが本番用のソースコードを置くようにする．
追加で **本番環境で見つけた緊急のバグ修正用ブランチとしてhotfix**があり，main/masterからブランチを作成し，main/masterとdevelopの両方に向けて統合する．
また， **リリース前のブランチとしてrelease** を作成する場合もある．

ブランチは2種類あり， **ローカルブランチ** と **リモートブランチ** の2種類がある．基本的にローカルとリモートは同じブランチ名のものが1対ずつある．しかしローカルでブランチを作成してもリモートではできないのでローカルで作成したらpush(後述)しよう．また逆も然りで，リモートで作成してもローカルでは作成されないのでcheckout(後述)しないとリモートブランチが反映されない．

### チェックアウト(checkout)
ローカルブランチを移動するための動作．作業するためには現在のブランチを意識することが必要である．ローカルブランチ間でしか移動できないので注意．リモートブランチで作業するということは絶対にない．gitはDVCSであることからローカルで行なった変更をリモートに同期するという動作が原則である．

### マージ(merge)
マージとは作成したブランチでの作業を他のブランチの統合する作業のことである．
リモートリポジトリでは直接マージをすることはなく，プルリクエストというものを作成し，マージするための要求をgithubなどで行う．そして，プルリクエストがレビューされ，承認された後，そのブランチの変更はメインブランチ（または指定されたブランチ）にマージすることとなる．マージが完了すると，プルリクエストのブランチを削除するかどうか選択できる．マージをすると基本マージコミットが作成され，そのコミットをマージ先のブランチにてプッシュすることで統合が完了する．
>プッシュについては後ほど説明する．

ローカルブランチではmergeコマンド(後述)であるブランチの変更点(作業)を他のブランチに統合する．
例えばfeatureブランチはdevelopmentブランチに向けてマージをし，developmentブランチはmainブランチに向けてマージする．
![スクリーンショット 2024-05-03 3.04.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/883b9a90-b7ff-22b3-d5d1-4ab8146e7ae8.png)

:::note warn
ローカルブランチでマージしてもリモートブランチには反映されない．ローカルでマージした後にリモートでpushするか．リモートで直接マージすること．
:::

ここではリモートブランチのマージの説明をする．

1．レビューが完了し，プルリクエストが承認されたら，"Merge pull request"ボタンをクリック．

![スクリーンショット 2024-05-03 3.27.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/dbf6ff62-925b-cdb5-2273-bc760f545604.png)



2．"Confirm merge"ボタンをクリックし，プルリクエストをマージする．

![スクリーンショット 2024-05-03 3.59.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/09ab9502-5015-1614-8e42-8a184a156d53.png)


3．マージが完成したので`feature/EXAMDEV-001ブランチ`は削除して良い．

![スクリーンショット 2024-05-03 3.52.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/32c97230-2e1d-cbf3-9ef6-1dbe98bd7aa0.png)


### プルリクエスト(Pull Request)
リモートリポジトリにおいて開発者が自分のブランチで行った変更を，mainブランチや他のブランチに統合してもらうために使用する．そして，他の開発者(プロジェクト管理者など)はその変更をレビューし，コメントやフィードバックを提供することができる．必要に応じて，プルリクエストの作成者は，フィードバックに基づいて変更を修正し，ブランチを更新(プッシュ)する．
> 一度あるブランチのプルリクエストを作成したらそのブランチにプッシュすればプルリクエストの内容が更新される．

>プッシュについては後ほど説明するのでブランチを現在の変更に更新するコマンドだと思ってほしい

プルリクエストはGitHubなどホスティングサービス上で行う．具体的には以下のように行う．
1．GitHubのリポジトリページに移動し，プルリクエストしたいブランチに移動する．
![スクリーンショット 2024-05-03 3.15.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/2f95241b-198f-0b64-11c2-738b408ebdf8.png)

2．"Pull requests"タブをクリックする．
![スクリーンショット 2024-05-03 3.16.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/6df09fa1-b3b0-1353-618d-91314264d709.png)

3．"New pull request"ボタンをクリックする．
![スクリーンショット 2024-05-03 3.21.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/acbef093-974c-6494-6c54-bb09800963d5.png)

4．"base"ブランチ（通常はmainまたはdevelopment）と"compare"ブランチ（プルリクエストを作成するブランチ）を選択する．
![スクリーンショット 2024-05-03 3.18.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/a51d84b6-6ae7-68f2-fa56-c1f004560ab2.png)
>今回は`feature/EXAMDEV-001ブランチ`から`developmentブランチ`にプルリクエストを作成する．

5．プルリクエストのタイトルと説明を入力する．
![スクリーンショット 2024-05-03 3.20.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/2c70040c-1425-3bd4-029d-929a2cafdfba.png)


6．必要に応じて，レビュー担当者やラベルを割り当てる．
![スクリーンショット 2024-05-03 3.21.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/e56e88a6-7795-e907-575b-07df8665da19.png)


7．"Create pull request"ボタンをクリックする．
![スクリーンショット 2024-05-03 3.51.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/f596162d-2256-8498-e96f-550bfc1fbd8e.png)


これでプルリクエストが作成できた．


### addとコミット(commit)
ローカルリポジトリにおいて何か変更をした際に変更を確定させるコマンド．基本的にgitでhん降を確定するにはIDEで編集してソースコードを保存しただけでは変更を確定できない．addをすることで確定する前段階の場所(ステージングエリア)にファイルを登録し，commitした際にステージングエリアの内容をもとに現在のブランチに対して変更を確定する処理をする．
つまり現在のリポジトリ(ワーキングディレクトリ)の変更をステージングエリアに追加(addコマンド)し，リポジトリの履歴に変更を記録する操作(commitコマンド)のこと．

**ワーキングディレクトリ**
プロジェクトのファイルが配置され，開発者が実際に作業を行う場所．

**ステージングエリア**
コミットする前の変更を一時的に保持する場所．

![スクリーンショット 2024-05-04 0.31.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/3064eaf8-8a07-2785-3353-7610a3c29462.png)

### プル(pull)
プルはリモートブランチからバージョン(コミット履歴)を取得し，現在のブランチに統合するためのGitコマンド．つまり他の開発者がリモートリポジトリを変更した際にその変更を自身のローカルリポジトリに適用させる動作のことである．

pullコマンドはリモートリポジトリの状態のみを同期し(fetchコマンド)，あるリモートブランチの変更を現在のローカルブランチに統合する(mergeコマンド)の二つを同時に実行するコマンド．


>**originとは**
>リモートリポジトリを表すデフォルトの名前．`git clone` コマンドを使用してリポジトリをクローンすると，クローン元のリポジトリが自動的に `origin` という名前で設定される．
>>つまり，`origin`は，リモートリポジトリの gitURLのことで，`origin/main`とはリモートリポジトリの main ブランチのこと 

![スクリーンショット 2024-05-04 0.06.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/f8c594ab-afbc-9909-f916-63ec0ca1697c.png)

:::note info
***リモートブランチとローカルブランチの違い***
リモートブランチとローカルブランチは連携して機能し，リモートブランチは，リモートリポジトリの状態を表し，他の開発者との共有や同期に使用される．ローカルブランチは，実際の開発作業を行うために使用され，必要に応じてリモートブランチと同期される．
:::

### プッシュ(push)
プッシュはローカルブランチのバージョン(コミット履歴)をリモートブランチに統合するGitコマンド．

commitをしただけではローカリリポジトリでしか変更を確定できていないのでリモートリポジトリに変更点を送信するために使用される．

![スクリーンショット 2024-05-04 0.41.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/0e55808d-a09e-d431-fce0-5dae010f0309.png)

一旦ここまでで，基礎知識を押さえておこう．基礎知識を知った上でさらに便利なコマンドを知っていくと良い．

git pushがrejectされたときの対処法はこちら

https://qiita.com/JavaLangRuntimeException/items/c0a1cb3b04d0ec30f81e

<!--
# git 内部構造
ここまで基礎知識を蓄えた上で中身も知らずにgitを使用するのは怖いなぁと思ったのでしっかり中身を理解してから使うべきだと思うので記載する．

ざっくりいうとgitの中身は
- gitオブジェクトというものの集まり
- 有向巡回グラフで管理している．
-->



# gitコマンド:gitの操作
ここではgitをCLIで操作するためのコマンドで特に便利なものを紹介する

## git init:ローカルリポジトリを初期化
あるディレクトリをローカルリポジトリとして新しく初期化する
```bash
git init
```

このローカルリポジトリを新しく作成したリモートリポジトリと紐づける方法を以下の記事で紹介している

https://qiita.com/JavaLangRuntimeException/items/cb1c4372d03cedc875b2

## git clone：リモートリポジトリからクローンする
リモートリポジトリからクローンする
```bash
git clone https://github.com/username/repository.git
```
特定のブランチ(developブランチ)をクローン
```bash
git clone -b develop https://github.com/username/repository.git
```

## git add：ファイルをステージングエリアに追加
ファイル，ディレクトリをステージングエリアに追加
```bash
git add <file-name/directory-name>
```
全ての変更をステージングエリアに追加
```bash
git add * 
```
カレントディレクトリをステージングエリアに追加
```bash
git add .
```
対話的にgit add をする
```bash
git add -i
```
対話的にgit addをすることで，変更点を確認しながら選択的にステージングエリアに追加できる．詳しくは以下の記事で説明しています．

https://qiita.com/JavaLangRuntimeException/items/21017a15501aff8985d7

## git rm:ワーキングディレクトリからファイルを削除
ワーキングディレクトリからファイル，ディレクトリを削除し，削除をGitのステージングエリアに追加する
```bash
git rm <file-name/directory-name>
```

## git clean:追跡されていないファイルの削除
追跡されていない（untracked）ファイルを削除する：
```bash
git clean -f
```
追跡されていないファイルとディレクトリを削除する：
```bash
git clean -fd
```
## git restore:変更を破棄する
ステージングされていないファイル，ディレクトリを破棄する：
```bash
git restore <file-name/directory-name>
```
全てのステージングされていない変更を破棄する：
```bash
git restore .
```
ステージング済みの変更を取り消す（変更自体は保持）：
```bash
git restore --staged <file-name/directory-name>
```
:::note info
これは以下のコマンドと同義
```bash
git reset --mixed HEAD <file-name/directory-name>
```
:::
## git status:作業ディレクトリとステージングエリアの状態を表示
ワーキングディレクトリとステージングエリアの状態を表示
```bash
git status
```

出力例:
```bash
On branch main
Your branch is up to date with 'origin/main'.

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:   file1.txt

Untracked files:
    (use "git add <file>..." to include in what will be committed)
        file2.txt

no changes added to commit (use "git add" and/or "git commit -a")
```

## git diff/show:変更差分を表示
ワーキングディレクトリの変更内容を表示するコマンドである．コミットされていない変更を確認したり，異なるコミット間やブランチ間の差分を見るのに使用される．

以下のコマンドはgit addする前に変更した箇所とインデックス(ステージングエリア)との変更点を参照する
```bash
git diff
```
出力例:
```bash
diff --git a/file1.txt b/file1.txt
index 1234567..abcdefg 100644
--- a/file1.txt
+++ b/file1.txt
@@ -1,3 +1,3 @@
This line remains unchanged.
-This line has been removed.
+This line has been added.
This line also remains unchanged.
```

- ブランチ間の差分を見る
..の右側が時系列的に新しい側なので注意
```bash
git diff branch1..branch2
```
- コミット間の差分を見る
```bash
git diff commit..commit2
```

- 今回コミットした変更点を見る
```bash
git diff HEAD^
```

- HEADとリモートとの変更点をみる
git pullする際に有用
```bash
git diff HEAD..origin/ブランチ名
```

- HEADとリモートとの変更点をみる
git push する際に有用
```bash
git diff origin/ブランチ名..HEAD
```

- ある1ファイルのみの変更点を見る
```bash
git diff -- <file path>
```
このコマンドは上述した他のブランチや他のコミットとの差分を見るコマンドとも組み合わせられる

- 別ファイルを比較する
```bash
git diff -- <file path1> <file path2>
```

- 改行や空白を無視
```bash
git diff -w
```

- git show(diffより詳細にコミット差分を表示)
```bash
git show HEAD
```
このコマンドはdiffに加えてコミットハッシュ,auther,dataが見れる．

:::note info
**git diffとgit statusの違い**
git statusは、現在のワーキングディレクトリとステージングエリアの状態を**概要的**に表示する。このコマンドは、**変更されたファイル**、**新しく追加されたファイル**、**削除されたファイル**、そして**ステージングエリアに追加されたファイルのリスト**を表示する。また、現在のブランチ名や、リモートリポジトリとの関係性も表示する。git statusは、**変更の有無を確認し、次に何をすべきかの概要を把握する**のに適している。

一方、git diffは、**より詳細な変更内容**を表示する。デフォルトでは、ワーキングディレクトリとステージングエリア間の違いを**行ごと**に表示する。具体的には、**どのファイルのどの部分が変更されたか**、**どの行が追加されたか**、**どの行が削除されたか**を示す。git diffには様々なオプションがあり、例えばステージングエリアとリポジトリの最新のコミットとの差分を見ることもできる。git diffは、変更の詳細を確認し、コードレビューや変更内容の精査に適している
:::

## git rev-list:指定されたコミットから到達可能なコミットの一覧を表示
git rev-listはコミット履歴の解析や特定のコミット範囲の操作に非常に有用．

- 全コミットの表示：
```bash
git rev-list HEAD
```
- 特定のブランチの最新n個のコミットを表示：
```bash
git rev-list -n 5 master
```
- 特定の日付以降のコミットを表示：
```bash
git rev-list --since="2023-01-01" HEAD
```
- 二つのコミット間の差分を表示(git diffと同じ)
```bash
git rev-list commit1..commit2
```
- マージコミットを除外：
```bash
git rev-list --no-merges HEAD
```
- 特定のファイルに影響を与えたコミットを表示：
```bash
git rev-list HEAD -- path/to/file
```
- 現在のブランチの総コミット数を表示する
```bash
git rev-list --count HEAD
```

これらの使用例は，git rev-listの多様な応用可能性を示している．
コミット履歴の分析，特定の変更の追跡，リポジトリの状態の把握など，様々な目的に活用できる．


## git blame:ファイルの各行において，いつ，誰が変更したのかを表示
ファイルの各行が最後に変更されたのはいつ，誰によってかを表示するコマンドである．コードの特定の部分の履歴や責任者を追跡する際に非常に有用である．
```bash
git blame filename.txt
```
出力例:
```
^1234567 (tarakokko3233 2023-08-15 10:30:45 +0900 1) This is the first line.
abcdefg8 (JavaLangRuntimeexception 2023-08-16 14:20:30 +0900 2) This is the second line.
```
## git commit：ステージングされた変更をリポジトリに記録
```bash
git commit -m "コミットメッセージ"
```

全ての変更をステージングしてコミット(git add *をしてからコミットと同等)
```bash
git commit -a -m "コミットメッセージ"
```
前のコミットに追加する形で前のコミットを修正
```bash
git add <変更したファイル>
git commit --amend -m "コミットメッセージ"
```
前のコミットのあるファイルを削除する形で前のコミットを修正
```bash
git rm <削除したいファイル>
git commit --amend -m "コミットメッセージ"
```

## git log:コミット履歴を表示
現在のブランチにおけるコミット履歴を表示
```bash
git log
```

`git log`と`git reflog`(以下で説明)の仕組みや，間違えて`reset --hard`して復旧したい際の詳しい説明は以下の記事から

https://qiita.com/JavaLangRuntimeException/items/103b0ae5a5dfc38312c2

## git reflog:ローカルリポジトリでの操作履歴を記録，表示
git reflogは主にHEADの移動履歴を記録する．具体的に**HEADを移動した際の操作履歴**とはgit commit，git branch，git resetするとHEADが移動するので記録が残る．

全ての操作履歴を表示
```bash
git reflog  
```
特定のブランチの操作履歴を表示
```bash
git reflog show <branch-name>
```

削除したブランチの復元:
```bash
git reflog
git checkout -b restored-branch <hash>  # reflogから見つけたハッシュを使用
```
リセットやリベースで失われたコミットの復元:
```bash
git reflog
git reset --hard <hash>  # 特定の状態に戻る
```
特定の時間前の状態に戻る:
```bash
git reflog
git checkout @{2.days.ago}  # 2日前の状態にチェックアウト
```

## git fsck:リポジトリの整合性をチェックをする
```bash
git fsck
```

実行後、何かの不具合がある場合はレ以下のようなメッセージが表示される．
```bash
missing blob <ハッシュ値> # ハッシュで指定されたブロブオブジェクトが見つからない
dangling commit <ハッシュ値> # コミットツリーやタグから参照されていないコミット
dangling blob <ハッシュ値> # コミットツリーやタグから参照されていないブロブオブジェクト
unreachable tree <ハッシュ値> # リファレンスから到達できないツリーオブジェクト
```
どのコミットやタグからも参照されていないオブジェクトを特定して出力
```bash
git fsck --unreachable
```
git fsck --unreachableに似ているが参照されていないオブジェクトを.git/lost-foundディレクトリに物理的に書き出す．
```bash
git fsck --lost-found
```
git fsck --lost-foundの使用例として，add した後にgit reset --hardしてしまった場合に失ったファイルを探したい
```bash
git fsck --lost-found

# 上記コマンドで見つかったオブジェクトを確認
cd .git/lost-found/other

# ファイルの内容を確認し，目的のファイルを見つける
cat < オブジェクトのハッシュ値 > 復元したいファイル名 # これでファイルの中身が表示される
```
:::note info
**git add したファイルはgit reflogで探せないのか**
結論から言うと，git addしたファイルはgit reflogに残らない．そのため，git reflogでは参照できない．
git reflogは主にHEADの移動履歴を記録する．つまり，以下のような操作が記録される．
- コミットの作成
- ブランチの切り替え
- リセット操作

このようにresetした履歴は残るがaddした履歴は残らないのでgit reflogではaddしたgit オブジェクトを参照できない．

しかし，git addしたファイルはblobオブジェクトとして保存されるのでgit fsckで参照がないblobオブジェクトを参照できる
> **blobオブジェクトとは**
> Gitには主に4種類のオブジェクトがある．
>
> - blob: ファイルの内容
> - tree: ディレクトリ構造
> - commit: コミットの情報
> - tag: タグの情報

:::


## git filter-branch : 大量のコミットの書き換えを機械的に行うオプション

過去から現在に至るまでのGitの歴史上から、そのファイルの痕跡を抹消したい場合
```bash
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch <消したいファイルのパス>" --prune-empty -- --all
```

## git branch：ブランチの作成、一覧表示、削除
![スクリーンショット 2024-05-03 3.02.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/086eb08a-52bf-9c3a-9228-6577db61577a.png)

Gitプロジェクトでは以下の3つの主要なブランチが使用されることが多い．

**main(master)ブランチ**
プロジェクトの主要なブランチで，製品版(本番環境)のコードを含む．**通常，直接このブランチに変更を加えることはない．**

**developmentブランチ**
開発用のブランチで，mainブランチから作成される．開発者は，このブランチで**新機能(featureブランチ)の統合**を行う．

**feature/--ブランチ**
新機能の開発やバグ修正のために，developmentブランチから作成される．各機能やバグ修正ごとに個別のfeatureブランチを作成する．開発が完了したら，featureブランチの変更はdevelopmentブランチにマージされる．**--は，その機能の名前をつける．**
> 機能名がEXAMDEV-001ならブランチ名はfeature/EXAMDEV-001とすると良い．

git branchコマンドは以下の操作をしている．
![スクリーンショット 2024-05-03 3.03.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/11137d08-b911-760c-d3f3-d552d1b54430.png)
ローカルブランチ一覧表示
```bash
git branch 
```
リモートブランチも表示
```bash
git branch -a
```
マージ済みのブランチを表示
```bash
git branch --merged
```
ブランチ作成
```bash
git branch <branch-name> 
```
特定のコミットからブランチを作成
```
git branch <ブランチ名> <コミットハッシュ>
```
ブランチ削除
(削除する際は他のブランチに移動してから)
```bash
git branch -d <branch-name>
```
ブランチ強制削除(マージできていないブランチなど強引に削除)
```bash
git branch -D <branch-name>
```

ブランチの名前変更
```bash
git branch -m <今のブランチ名> <新しいブランチ名>
```

各ブランチの最新のコミットを表示
```bash
git branch -v
```

## git checkout：ブランチの切り替え
ブランチ切り替え
```bash
git checkout <branch-name>
```
新しいブランチを作成して切り替え
```bash
git checkout -b <new-branch-name>
```

## git switch：ブランチの切り替え
ブランチ切り替え
```bash
git switch <branch-name>
```
新しいブランチを作成して切り替え
```bash
git switch -c <new-branch-name> 
```


## git reset(revert)：コミットを取り消す，ステージングを解除する
git reset git revertに関しては以下の記事から(説明が難しいのでこちらで)

https://qiita.com/JavaLangRuntimeException/items/38de3bf197fc2a262d4b

initial commitのreset方法は以下の記事から



resetは取り消し対象のコミットが残らない
直前のコミットを取り消し，変更をステージングエリアに保持する：
```bash
git reset --soft HEAD^
```

直前のコミットを取り消し，変更をワーキングエリアに保持する：
```bash
git reset --mixed HEAD^
```
直前のコミットを完全に取り消し，変更も破棄する：
```bash
git reset --hard HEAD^
```

直前のコミットの取消操作をコミットする(取り消し対象のコミットが残る)
```
git revert HEAD^
```

:::note info
HEAD^の部分はHEAD^nにすればnこ前のコミットまで取り消せる

また， 特定のコミットまで戻し，それ以降の変更を全て破棄することもできる
```bash
git reset --mixed <commit-hash>
```
:::

:::note warn
reset操作が終わりリモートにプッシュする際は強制プッシュすること
```bash
git push -f origin main
```
:::



## git stash：作業中の変更を一時的に保存
stashに関しては以下の記事で詳しく記載している

https://qiita.com/JavaLangRuntimeException/items/d70dcfa530deaf519af1

git追跡済みの変更を一時保存(stash)する
```bash
git stash push
```
> addしたものをstashする際はこのコマンド

追跡外のファイル含めて一時保存(stash)する
```bash
git stash push -u
```

変更をメッセージを付けて一時保存（stash）する
```bash
git stash push "作業中の変更"
```

作業ディレクトリに最新の一時保存した状態を適用し，最新のstashはstashリストから削除される
```bash
git stash pop
```
最新のstashを適用するが、stashリストからは削除しない
```bash
git stash apply
```
特定のstashを適用
ここで、nは`git stash list`で表示されるインデックス番号
```bash
git stash apply stash@{n}
```
stashした一覧を表示:
```bash
git stash list
```

## git rebase:コミットの編集
git rebaseに関しては以下の記事から(説明が難しいのでこちらで)

https://qiita.com/JavaLangRuntimeException/items/49a5f0c0b297baa0568e

リベースをする
```md:HEAD(現在の作業位置)からnこ分のコミット履歴を表示する
git rebase -i HEAD~n
```
リベース中の変更を破棄し，リベースを中止する：
```bash
git rebase --abort
```

## git grep:リポジトリ内の全ファイル内での文字列検索
"a"をローカルリポジトリ内で探す
```bash
git grep "a"
```
## git archive:ローカルリポジトリのアーカイブを作成
現在のブランチのHEADの時点のローカルブランチで`archive.zip`という名前のzipファイルでアーカイブを作成する
```bash
git archive --format=zip HEAD > archive.zip
```


## git merge:他のローカルブランチの内容をマージする
現在のローカルブランチに他のローカルブランチの内容をマージする
```bash
git merge <ブランチ名>
```
コンフリクトが起きた際にマージ中の変更を破棄し，マージを中止する：
```bash
git merge --abort
```

マージの際には三種類の方法がある．

**Create a merge commit**
マージ時に新しいコミット（マージコミット）を作成し，両方のブランチの履歴を保持する．履歴が複雑になるが，マージの経緯を追跡できる．
コマンドでは以下の通りでできる．作業ブランチをマージ先のブランチにする．
これが先述したデフォルトのmergeコマンドである．
```
git merge <統合したいbranch名>
```

**Squash and merge**
マージ元のブランチのすべてのコミットを1つのコミットに圧縮（スカッシュ）してから，マージ先のブランチにマージする．つまり，マージ元のブランチの個別のコミットは失われ，すべての変更が1つのコミットにまとめられる．履歴がシンプルになるが，マージ元のブランチの個別のコミットを追跡できなくなる．
コマンドでは以下の通りでできる．作業ブランチをマージ先のブランチにする．
```
git merge --squash <統合したいbranch名>
git commit
```

**Rebase and merge**
マージ元のブランチの変更をマージ先のブランチにリベース（再配置）してから、マージを行う．マージ元のブランチのコミットは，マージ先のブランチの先頭に順番に追加されることで，履歴がマージ先のブランチにまとまり，マージコミットは作成されない．
コマンドでは以下の通りでできる．作業ブランチをマージ先のブランチにする．
```
git rebase <統合したいbranch名>
git merge <統合したいbranch名>
```

## git cherry-pick:特定のコミットの変更内容を現在のブランチに適用する
特定のコミットの変更内容を現在のブランチに適用するコマンドである．このコマンドは，他のブランチからコミットを選択的に取り込む際に非常に有用．
選択したコミットの内容を基に，新しいコミットを作成するため、他のブランチで行われた変更を，そのブランチ全体をマージすることなく再利用できる。

作業するブランチにcheckout/switchしてから以下のコマンドを実行する
```bash
git cherry-pick <commit-hash>
```

具体的な使用例:
- 単一のコミットを適用
```bash
git cherry-pick abc123
```
- 複数のコミットを連続して適用
```bash
git cherry-pick abc123 def456 ghi789
```   
- コミット範囲を適用
```bash
git cherry-pick abc123^..def456
```
:::note warn
**注意点:**
**1. コンフリクト:**
   cherry-pickを実行する際，現在のブランチの内容とコンフリクトが発生する可能性がある．その場合，手動でコンフリクトを解決する必要がある．

**2. コミット履歴:**
   cherry-pickは新しいコミットを作成するため，元のコミット履歴とは異なる履歴が作成される．

**3. 重複適用:**
   同じ変更を複数回適用すると，重複や予期せぬ結果を招く可能性がある．

**4. コミットメッセージ:**
   デフォルトでは元のコミットメッセージが使用されるが，-eオプションを使用して編集することも可能である．
:::
:::note info
**git mergeとgit cherry-pickの違い**
mergeはブランチ全体の変更履歴を統合し，マージコミットを作成する．これは長期的なdevelopmentブランチの統合や，featureブランチの完成後の統合に適している．元のブランチとの関係性が明確に保持され，チーム開発の標準的なワークフローに組み込まれやすい．

cherry-pickは特定の個別コミットを選択的に適用する．これは特定のバグ修正や機能を別ブランチに適用する際に有用である．新しいコミットが作成されるため，元のコミットとの直接的な関連性は失われる．より特殊なケースや緊急時の対応に使用されることが多い．

> mergeはブランチ全体を扱うため複数箇所でコンフリクトが発生する可能性があるが，cherry-pickはコンフリクトの範囲が限定的になりやすい．
:::


## git fetch：リモートの状態をマージせずローカルと同期
リモートの状態をローカルに同期(マージはしない)
```bash
git fetch origin
```
リモートで削除されたローカルブランチを削除した状態で同期(マージはしない)
```bash
git fetch --prune
```

## git push：ローカルの変更をリモートリポジトリに同期
```bash
git push origin <ブランチ名>
```

強制的に push（resetした際などコミットがリモートよりローカルが遅れている際に使用）
```
git push -f origin main
```

ローカルブランチに対応するリモートブランチがない場合にpushする
```bash
git push --set-upstream origin feature/sample
```
> ブランチをローカルで作成してまだpushしたことない場合にこのコマンドを使用する

`git push --set-upstream` を省略して `git push`のみでpushできる

https://qiita.com/JavaLangRuntimeException/items/cde292638187221f61a3

git pushがrejectされたときの対処法はこちら

https://qiita.com/JavaLangRuntimeException/items/c0a1cb3b04d0ec30f81e

## git pull：リモートの変更をローカルリポジトリに取り込む
リモートのmainブランチの変更をローカルに取り込む
```bash
git pull origin main
```
rebaseをしながらpullする
```bash
git pull --rebase origin main
```
rebaseについては以下の記事から

https://qiita.com/JavaLangRuntimeException/items/49a5f0c0b297baa0568e

## git remote: リモートリポジトリとローカルリポジトリを繋ぐ設定
現在のリポジトリに設定されているリモートリポジトリの一覧を表示する．
```bash
git remote
```
git remoteの出力に加えてリモートリポジトリのURLも表示される．
```bash
git remote -v
```
新しいリモートリポジトリを追加する．`origin`は一般的に使用されるリモート名である．
```bash
git remote add origin <リモートリポジトリのURL>
```
リモートリポジトリの名前を変更する．
```bash
git remote rename <old_name> <new_name>
```
指定したリモートリポジトリをローカルリポジトリから削除する．
```bash
git remote remove name
```
既存のリモートリポジトリのURLを変更する．
```bash
git remote set-url origin <リモートリポジトリのURL>
```
指定したリモートリポジトリの詳細情報を表示する．
```bash
git remote show origin
```


# ghコマンド:githubの操作用
ここからは以下の動作をしていることを前提で

:::note warn
githubCLIのコマンが入っていない人はインストールすること
```
brew install gh 
```
:::

githubCLIにログインする
```
gh auth login 
```
`GitHub.com`か`GitHub Enterprise Server`かを選択する．個人利用なら`GitHub.com`を選択すれば良い，
```
? What account do you want to log into?  [Use arrows to move, type to filter]
> GitHub.com
  GitHub Enterprise Server
```

`HTTPS`か`SSH`を選択する
```
? What is your preferred protocol for Git operations on this host?  [Use arrows to move, type to filter]
> HTTPS
  SSH
```
`Y`と入力してEnter
```
? Authenticate Git with your GitHub credentials? (Y/n)
```
`Login with a web browser`で良いと思う．ブラウザでgithubへログインすることになる．
```
? How would you like to authenticate GitHub CLI?  [Use arrows to move, type to filter]
> Login with a web browser
  Paste an authentication token
```
その後，以下のように表示されるのでone-time codeを控えておく．

:::note info
0000-0000は英数字で表示され，ユーザ，タイミングによって異なる値である．
:::

```
! First copy your one-time code: 0000-0000
Press Enter to open github.com in your browser...
```
web上でone-time codeを入力し，githubにログインすると以下のように表示される．

```
✓ Authentication complete.
- gh config set -h github.com git_protocol https
✓ Configured git protocol
✓ Logged in as <githubアカウント名>
```

## gh browse:リモートをgithub.comでアクセス
現在のローカルリポジトリに対応するリモートリポジトリをgithub.comで開く
```bash
gh browse
```

## gh repo:リモートリポジトリの操作
gh repo createに関しては以下の記事から

https://qiita.com/JavaLangRuntimeException/items/cb1c4372d03cedc875b2


**リモートリポジトリの作成**
このコマンドでリモートに新しくリポジトリを作成する．
```md:プライベートリポジトリなら
gh repo create <リモートリポジトリ名> --private
```
```md:パブリックリポジトリなら
gh repo create <リモートリポジトリ名> --public
```

自分のGithubアカウントに紐付いた組織アカウントにリモートリポジトリを作成するなら
```md:プライベートリポジトリなら
gh repo create <組織アカウント名>/<リモートリポジトリ名> --private
```

リモートに新しくgitignoreを追加した状態でリモートリポジトリを作成する
```md:プライベートリポジトリなら
gh repo create <リモートリポジトリ名> --private --gitignore <作成したいgitignoreテンプレート>
```
:::note info
例えば，Unityのgitignoreを追加したい場合
```bash
gh repo create <リモートリポジトリ名> --private --gitignore Unity
```
:::

**リポジトリの削除**
```bash
gh repo delete <repo-name>
```

**リポジトリのクローン**
ログインしたアカウントからのリモートリポジトリをクローンする．
```bash
gh repo clone <アカウント名>/<リポジトリ名>　
```
<アカウント名>を省略するとログインしているメインユーザーでのリポジトリから探すようになる．組織アカウントからクローンしたい場合は<アカウント名>に組織アカウント名を入力すること．

:::note info
これは以下のコマンドを実行をしているのと同じ
```bash
git clone https://github.com/<アカウント名>/<リポジトリ名>　.git
```
:::

ブランチを指定してクローンも可能．この例はdevelopブランチをクローンしている
```bash
gh repo clone <アカウント名>/<リポジトリ名>　 -- -b develop
```


## gh pr:プルリクエストの操作
プルリクエストのコメントの書き方は以下の記事から

https://qiita.com/JavaLangRuntimeException/items/329eb92a47a07ff4dde8

github.com上でPR一覧を開く
```bash
gh pr list --web
```
現在のブランチからdevelopブランチへプルリクエストを作成
```bash
gh pr create --title "タイトル" --body "説明" --base develop
```
プルリクエストの一覧表示
オープン中ののPRの一覧を表示する方法
```bash
gh pr list
```
closedのPRの一覧を表示する
```bash
gh pr list --state closed
```
:::note info
--stateの後に以下を入力すれば他の状態のPRを表示できる
`all` 全てのPR
`marged` マージずみのPR
:::

自分に割り当てられたPRを確認
```bash
gh pr list --assignee @me
```

特定のユーザーのPRを確認
```bash
gh pr list --author <ユーザーネーム>
```
PRをクローズしたい
```bash
gh pr close <ブランチ名またはPR番号>
```
PRをクローズし，該当するブランチを削除したい
```bash
gh pr close <ブランチ名またはPR番号> --delete-branch
```
あるブランチからのプルリクエストをマージ
```bash
gh pr merge <ブランチ名またはPR番号>
```
## gh issue:イシューの操作
イシューの作成
```bash
gh issue create --assigneen <ユーザネーム> --title "タイトル" --body "内容" 
```

イシューの一覧表示
```bash
gh issue list
```
## gh workflow:ワークフロー操作

ワークフローの一覧表示：
```bash
gh workflow list
```

ワークフローの実行
```bash
gh workflow run <workflow>
```

ワークフロー実行の表示
```bash
gh run view <run-id>
```