git ワークツリー, ステージ, ローカルリポジトリ 関連

### 前書き等
###### 注意
　このページに書かれていることは、筆者の考え方になります。また、筆者のメモの意味合いが強いです。そのため、語句の意味が実際とは異なる可能性があります。

###### 目次
　　**[前書き等](#前書き等)**
　　　 **[注意](#注意)**
　　　 **[目次](#目次)**
　　　 **[用語](#用語)**
　　**[本文](#本文)**
　　　 **[記号](#この記事では各場所を記号で表します)**
　　 **ｰ[追加系](#追加系)**
　　 **ｰ[削除系](#削除系)**
　　 **ｰ[反映系](#反映系)**
　　 **ｰ[復元系](#復元系)**
　　 **ｰ[履歴改変系](#履歴改変系)**
　　 **ｰ[参照先変更系](#参照先変更系)**
　　**[引用元、参照元、参考先](#引用元参照元参考先)**

###### 用語
**＜３つのエリア＞**
たぶん、大体、
・"**ワークツリー**"
　　 ＝ワーキングツリー
　　 ＝作業ディレクトリ
　　 ＝砂場
・"**ステージ**"
　　 ＝インデックス
　　 ＝キャッシュ
　　 ※ステージに上げること＝ステージング
　　 ※ステージから降ろすこと＝アンステージ
・"**ローカルリポジトリ**"
　　 ＝データベース
　　 ＝情報格納庫
　　 ＝コミット（＝ファイルの情報群）を束ねたもの
<font color="Gray">※エリアは“領域”という意味で使っています</font>
<font color="DimGray">※ tree 構造（ディレクトリ・ファイル名）
※ blob オブジェクト（圧縮されたファイル本体）
※ tree オブジェクト（" tree 構造"＋" blob オブジェクトのハッシュ値"）
※ commit オブジェクト（" tree オブジェクトのハッシュ値"＋"詳細情報の記録"）
※コミット（ファイルの情報群）
　（Git において ”コミット” は名詞と動詞があるらしい "[commit](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefcommitacommit)"）
注：この記事では "コミット" は名詞とし、動詞は "git commit する" と表記します
注：『履歴』ｰ commit オブジェクトは、自身の親の commit オブジェクトのハッシュ値を含むため、結果として 最初～最新 すべての連綿とした繋がりを知ることが出来ます（＝歴史とも）
注：『   :/  』ｰ "リポジトリのルート"（単独なら、それぞれのエリアでの、まるごと全部）を表します。":/" のみを指定することは、コマンドのオプションで言えば "--all" を付けるみたいなものです。
　（ :"magic signature…":\<pathspec\>、:("magic word","･･･","･･･")\<pathspec\> ）**↓例**
　（ :/:\<pathspec\> 　　　　　　　　、:(top)\<pathspec\> ）
注：『参照先』ｰ ｢"HEAD"｣ → ｢".git/refs/heads/ブランチ名"＝"Commit ID"｣（ HEAD はシンボリックリンクになっています）
注：『参照』ｰ 各ブランチが指す最新のコミットのこと（参照を辿る：各ブランチの先頭のコミットが指す親コミットを遡っていくこと）。さらに Git 自身が保持する参照履歴（reflog）もあります。</font>



### 本文
###### この記事では各場所を記号で表します
⨇：work_tree（作業ディレクトリ）
⏢：stage（インデックスに記載されている状態）
⧉：ローカルリポジトリ（データベース：情報格納庫）
✖：削除
⏵⨇⟶⏢⟶⧉
⏴⨇⟵⏢⟵⧉


#### 追加系
⏵⨇⟶⏢
**git add -- \<file\>**
　：ファイルを stage に上げる
　・処理は、**1** .git/objects に blob オブジェクトを作成（圧縮されたファイル本体）
　　　　　　　<font color="Gray">※ひたすら**追加**、"rm -f .git/objects/dir/file か git gc --prune=now" しない限りたぶんなくならない</font>
　　　　　　**2** .git/index に tree 構造（ディレクトリ・ファイル名）が記載される（**追記**）
　　　　　　　<font color="Gray">※ "--all" 、":/" 、"." を指定したときは**上書き**</font>
　※ cache は .git/index に残っている情報のこと


⏵⏢⟶⧉
**git commit**
　：ファイル情報をローカルリポジトリ（データベース）に記録する
　・処理は、**1** .git/index から、blob オブジェクトのハッシュ値も含めた tree オブジェクトを作成
　　　　　　**2** tree オブジェクトのハッシュ値を含めた、commit_id で管理される commit オブジェクトを作成（詳細情報を記録）


#### 削除系
⏵⨇⟶✖
**rm \<file\>**
　・処理は、**1** work_tree のファイルを削除する


⏵⏢⟶✖
**git rm --cached -- \<file\>**
　：ファイルを stage から降ろす
　・処理は、**1** .git/index に残っている記載を削除する


⏵⏢⟶✖, ⨇⟶✖
**git rm -- \<file\>**
　：ファイルを stage から降ろし、work_tree から削除する
　・処理は、**1** .git/index に残っている記載を削除する
　　　　　　**2** work_tree のファイルを削除する


#### 反映系
⏵⨇⟶⏢
**git update-index --remove --stdin \< \<(git ls-files :/)**
　<font color="Gray">（ git update-index --remove -- \<file\> は ｢ . ｣ で始まるものと ｢ / ｣ で終わるものが無視される）</font>
　<font color="Gray">（ --stdin は空白ではなく改行をファイル名の区切りとする）</font>
　：work_tree でのファイルの削除を stage にも反映する
　・処理は、**1** 現在のディレクトリから再帰的に stage の情報を取得し、work_tree から削除したファイルのファイル名（＋階層構造）を、.git/index から削除する


#### 復元系
⏴⨇⟵⏢
**git restore -- \<file\>**
　<font color="Gray">（オプションなしの git restore は --worktree が付与され、かつ stage から復元）</font>
**git checkout-index --force -- \<file\>**
　<font color="Gray">（ git checkout-index は "--prefix=directory/" で保存先を指定可能）</font>
　：ファイルを stage から work_tree に復元する
　・処理は、**1** .git/index に記載されている tree 構造で blob オブジェクトを work_tree に展開し、指定されたファイルが上書きされる


⏴⏢⟵⧉
**git restore --staged -- :/**
　<font color="Gray">（ commit_id を指定しない場合 git restore は HEAD が指定される）</font>
**git reset -- :/**
**git reset**
　<font color="Gray">（一切の引数がない git reset は **"git reset --mixed HEAD"** が実行される）</font>
　：ローカルリポジトリにある最新のコミット（ファイルの情報群）を stage に戻す
　・処理は、**1** 最新の commit_id から tree オブジェクト（ blob オブジェクトのハッシュ値を含む）を指定し、内容を .git/index に記載（**上書き**、:/\<file\> にした場合はそのファイルのみ上書き<font color="Gray">他はそのまま</font>）


⏴⨇⟵⧉
**git restore --source \<commit id\> -- :/**
　<font color="Gray">（既定で --worktree が付与）</font>
　<font color="Gray">（ --source を指定した場合は、既定で --no-overlay ）</font>
　：ローカルリポジトリの指定されたコミットから work_tree にファイルを復元する
　・処理は、**1** 指定された commit_id から tree オブジェクト・blob オブジェクトを指定、コミットの持つ tree 構造に一致するように、work_tree の該当部分がすべて上書きされる（ \<file\> を指定した場合はそのファイルのみ、サブディレクトリを指定した場合はサブディレクトリ全体のみ、**上書き** ； ファイルとディレクトリ両方において、**未追跡**（<INS>一度もステージに上げたことがない</INS>・<INS>管理除外対象に登録している</INS>）なものは削除されない。）


⏴⏢⟵⧉, ⨇⟵⧉
**git restore --staged --worktree --source \<commit id\> -- :/**
　<font color="Gray">（省略系： git restore -SW -s \<commit id\> :/ ）</font>
　<font color="Gray">（ --source を指定した場合は、既定で --no-overlay ）</font>
　：ローカルリポジトリの指定されたコミットから stage, work_tree にファイルを復元する
　・処理は、**1** 指定された commit_id から tree オブジェクトを指定、内容を .git/index に記載（**上書き**、:/\<file\> にした場合はそのファイルのみ上書き<font color="Gray">他はそのまま</font>）
　　　　　　**2** 指定された commit_id から tree オブジェクト・blob オブジェクトを指定、コミットの持つ tree 構造に一致するように、work_tree の該当部分がすべて上書きされる（ \<file\> を指定した場合はそのファイルのみ、サブディレクトリを指定した場合はサブディレクトリ全体のみ、**上書き** ； ファイルとディレクトリ両方において、**未追跡**（<INS>一度もステージに上げたことがない</INS>・<INS>管理除外対象に登録している</INS>）なものは削除されない。）


#### 履歴改変系
⏴⧉^⟵~~⧉~~
**git reset --soft HEAD^**
　：一番最後の「**git commit** をした」という履歴を、ローカルリポジトリから消す
　・処理は、**1** 最新の commit_id を HEAD から外し、１つ前の commit_id を HEAD とする


⏴⧉^⟵~~⧉~~, ⏢⟵⧉^
**git reset --mixed HEAD^**
**git reset HEAD^**
　<font color="Gray">（ --mixed は既定値）</font>
　：一番最後の「**git commit** をした」という履歴をローカルリポジトリから消し、１つ前のコミットから stage にファイルを復元する
　・処理は、**1** 最新の commit_id を HEAD から外し、１つ前の commit_id を HEAD とする
　　　　　　**2** １つ前の commit_id から tree オブジェクトを指定、内容を .git/index に記載（**上書き**）


⏴⧉^⟵~~⧉~~, ⏢⟵⧉^, ⨇⟵⧉^
**git reset --hard HEAD^**
　：一番最後の「**git commit** をした」という履歴をローカルリポジトリから消し、１つ前のコミットから stage, work_tree にファイルを復元する
　・処理は、**1** 最新の commit_id を HEAD から外し、１つ前の commit_id を HEAD とする
　　　　　　**2** １つ前の commit_id から tree オブジェクトを指定、内容を .git/index に記載（**上書き**）
　　　　　　**3** １つ前の commit_id から tree オブジェクト・blob オブジェクトを指定、ディレクトリ構造ごと work_tree に展開され、<font color="Red">指定されたファイル・ディレクトリのみの状態に work_tree 全体が**上書き**される</font>（ファイルとディレクトリ両方において、**未追跡**（<INS>一度もステージに上げたことがない</INS>・<INS>管理除外対象に登録している</INS>）なものは削除されない。）


#### 参照先変更系
⏵⧉⟶⧉**´**
**git update-ref refs/heads/$(git branch --show-current) \<commit id\>**
**git reset --soft \<commit id\>**
　：現在のブランチの、ローカルリポジトリの履歴の参照先を書き換える
　・処理は、**1** "refs/heads/ブランチ名" の最新のコミット参照先を、指定した commit_id に置き換える

### 引用元、参照元、参考先
Git コマンドリファレンス（日本語版）
　・https://tracpath.com/docs/git-reset/
　・https://tracpath.com/docs/git-restore/
　・https://tracpath.com/docs/git-rm/
Git Documentation
　・https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt
　・https://git-scm.com/docs/git-rev-parse#Documentation/git-rev-parse.txt---absolute-git-dir
　・https://git-scm.com/book/ja/v2/Git-の基本-変更内容のリポジトリへの記録
　・https://git-scm.com/book/ja/v2/Git-のさまざまなツール-リセットコマンド詳説
アクティビティ: Git によるバージョン管理
　・https://tmytokai.github.io/open-ed/activity/git/text01/page04.html
　・https://tmytokai.github.io/open-ed/activity/git/text02/page07.html
　・https://tmytokai.github.io/open-ed/activity/git/text02/page08.html
Git reset で HEAD位置を変えないとき
　・https://masuyama13.hatenablog.com/entry/2020/08/24/235327
[git reset (--hard/--soft)]ワーキングツリー、インデックス、HEADを使いこなす方法
　・https://qiita.com/shuntaro_tamura/items/db1aef9cf9d78db50ffe
【Git&GitHub】ファイルの削除を記録（git rmコマンド）
　・https://phoeducation.work/entry/20210806/1628204280
git add､git commitの保存先と取消コマンドについて
　・https://qiita.com/s56258/items/62e14b27d6c7ed216fa5
git add の取り消し方法と、関連コマンドまとめ
　・https://www-creators.com/archives/1282
Gitのコミットの裏側で起こっていること
　・https://made.livesense.co.jp/entry/2017/08/22/080000
Gitのステージング領域の正体を探る
　・https://engineering.mercari.com/blog/entry/2017-04-06-171430/
TypeScriptでGitを自作した話
　・https://zenn.dev/akashixi/articles/18e386e810b280
Gitのインデックスの中身
　・https://zenn.dev/kaityo256/articles/inside_the_index
【Git】インデックスとは？【図解でわかり易く解説】
　・https://tetoblog.org/2021/06/git-index/
[git] Gitの内部（ツリーオブジェクト）
　・https://www.yoheim.net/blog.php?q=20140301
【Git】git cleanの使い方を実例で解説。「-f」と「-df」とは何か？｜Untracked files（未追跡ファイル）やディレクトリを削除する方法
　・https://prograshi.com/general/git/git-clean/
汚してしまったGitワークツリーをヘッドリビジョンに戻す
　・https://lab.unicast.ne.jp/2011/06/02/汚してしまったgitワークツリーをヘッドリビジョ/
gitでuntrackedなファイルを一括削除する方法
　・https://hacknote.jp/archives/7130/