GitHubでリポジトリ作成してプッシュまでを勉強しながら進めていった

## 前提
- GitHubでリポジトリ作成済み
- EclipseでSpringプロジェクト作成済み

### 使用環境・ツール
- mac
- Finder
- ターミナル
- GitHub

## さっそくやっていきます
まず以下のような構成でフォルダを作成します。
```
/Users/username/DevProjects
├── SpringProjects
　   └── my-app-spring
```

SpringProjectsフォルダに移動します。
```
% cd DevProjects/SpringProjects/my-app-spring
```

git initします。
```
% git init
Initialized empty Git repository in /Users/username/DevProjects/SpringProjects/my-app-spring/.git/
```

ローカルに.gitフォルダが作成されました。
```
% ls -A
.classpath	.mvn		HELP.md		pom.xml
.git		.project	mvnw		src
.gitignore	.settings	mvnw.cmd	target
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790294/621d319c-c6f6-1476-9942-02532e5edac9.png)

.gitフォルダに移動してみます。
```
% cd .git
```

.gitフォルダ内のファイル一覧。
```
% ls
HEAD		description	info		refs
config		hooks		objects
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790294/4a7017e0-3b36-7e49-b3f7-92dc55365567.png)


それぞれの役割をchatGPTに聞いてみました。
|ファイル/フォルダ名|役割|
|-|-|
|config|Gitリポジトリの設定ファイル。リポジトリ固有の設定が含まれています。|
|hooks|リポジトリに関連するスクリプトが配置されるディレクトリ。コミット前やプッシュ後などのイベントにフックされるスクリプトが含まれます。|
|objects|Gitのデータベース。コミットやツリー、ブロブなどのオブジェクトがSHA-1ハッシュ値に基づいて保存されます。|
|HEAD|現在チェックアウトされているブランチの参照を保持するファイル。|
|description|Gitリポジトリの説明を含むファイル。通常、Gitウェブインターフェースで表示される説明文がここに書かれます。|
|info|リポジトリに関する追加情報が含まれるディレクトリ。特にexcludeファイルは、.gitignoreと同様に無視するパターンを指定します。|
|refs|ブランチやタグの参照情報を保持するディレクトリ。|

おそらくdescriptionはGitHubでリポジトリ作成した時に書いた説明のところが入ってくる？
その他、configとHEADファイルの内容を確認してみます。
```
% cat HEAD
ref: refs/heads/main
```
```
% cat config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = true
```
つまり、HEADから分かることは「現在チェックアウトされているブランチの参照を保持するファイル」はrefs/heads/mainということになります。

「Gitリポジトリの設定ファイル」であるconfigに関してもchatGPTで聞いてみました。
|設定名|説明|
|-|-|
|repositoryformatversion|リポジトリフォーマットのバージョン。通常は0です。|
|repositoryformatversion|trueの場合、Gitはファイルの実行権限（パーミッション）を管理します。|
|bare|falseの場合、このリポジトリはワーキングディレクトリを持つ標準的なリポジトリです。trueの場合、ワーキングディレクトリを持たないベアリポジトリになります。|
|logallrefupdates|trueの場合、リファレンス（ブランチやタグ）の更新をすべて記録します。|
|ignorecase|trueの場合、Gitはファイル名の大文字と小文字を区別しません。主にWindowsやmacOSで使われます。|
|precomposeunicode|trueの場合、Unicodeの正規化を行います。主にmacOSで使われ、Unicodeの合成文字を分解せずにそのまま扱います。|

.gitフォルダ内にrefsフォルダがあるのでその先に進んで。「現在チェックアウトされているブランチ」のmainを確認していきます。
```
% cd refs/heads/main
cd: no such file or directory: refs/heads/main
```
まだ存在しませんでした。

これについてもchatGPTに聞いてみたところ、
「git initコマンドを実行すると、Gitは新しいリポジトリを初期化し、必要なディレクトリやファイルを作成しますが、ブランチ自体はまだ作成されません。」
とのことでした。
ということで参照自体は作成されているけど、実体はまだないというようなことみたいです。

## Springプロジェクトのファイルをコミットしてみます
流れとしては、ステージングというのを行なってファイルをコミット対象としてからコミットするみたいです。
ステージングするためにgit addしていきます。今回は試しにpom.xmlを初回コミットしてみます。

```
% git add pom.xml
```
このコマンド打った後はターミナル上では何も起きませんでした。
git statusで状態を確認できるみたいです。

```
% git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
	new file:   pom.xml

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.DS_Store
	.gitignore
	.mvn/
	mvnw
	mvnw.cmd
	src/
```
git addしたpom.xmlが無事コミット対象されたみたいです。
コミット対象となったので、コミットしていきます。

```
% git commit -m "Initial commit"
[main (root-commit) 9cf7788] Initial commit
 1 file changed, 64 insertions(+)
 create mode 100644 pom.xml
 ```

 ログも確認します。うまくいってそうです。
 ```
 git log
commit ハッシュ値 (HEAD -> main)
Author: 名前 <メールアドレス>
Date:   Tue May 21 20:12:29 2024 +0900
 ```

ということで先ほど、参照は作成されたけど実態がなかったrefs/heads/mainを確認してみます。
headsに移動します
 ```
% cd .git/refs/heads     
heads %
```
mainができていました。
```
% ls
main
```
つまり改めて整理すると
|コミット前|コミット後|
|-|-|
|git initコマンドでリポジトリが初期化され、参照が設定されるが、まだ実際のコミットオブジェクトは存在しないためrefs/heads/mainはない。|git commitコマンドを実行すると、実際のコミットオブジェクトが作成され、そのハッシュ値がrefs/heads/mainファイルに保存される。|

## Githubとローカルのリポジトリを連携していく
事前にGitHubで作成しておいたリポジトリとここまで頑張って作業して作成してきたローカルリポジトリを連携させます。git remote addで連携できます。つまりこれを行うことで、この後のプルやプッシュができる対象となるみたいです。
```
% git remote add origin https://github.com/自分のgithubのユーザ名/リポジトリ名.git
```
確認します。originというのがあります。これはリモートリポジトリのことです。
うまくいってそうです。
```
% git remote 
origin
```

続いて、Githubでリポジトリ作成した時に、ライセンスファイルやREADMEファイルを付けて作成したので、それを取り込む作業が必要です。今回はfetchしてmergeしていきたいと思います。
fetchします。
```
 % git fetch origin
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), 1.59 KiB | 325.00 KiB/s, done.
From https://github.com/ユーザ名/リポジトリ名
 * [new branch]      main       -> origin/main
```
mergeします。
```
% git merge origin/main --allow-unrelated-histories
Merge made by the 'ort' strategy.
 LICENSE   | 21 +++++++++++++++++++++
 README.md |  2 ++
 2 files changed, 23 insertions(+)
 create mode 100644 LICENSE
 create mode 100644 README.md
```
無事にライセンスファイルとREADEMEファイルがマージされたみたいです。


## プッシュしていきます
最後にプッシュしていきます
```
% git push origin main
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 1.22 KiB | 1.22 MiB/s, done.
Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/ユーザ名/リポジトリ名.git
   9fc9989..bf816a2  main -> main
```
無事プッシュできたみたいです。

GitHubも確認してみたところpom.xmlがしっかり反映されていました。

## まとめ
今までの流れをまとめてみます。
①git initでローカルリポジトリを初期化する。
②git addでステージングしファイルをコミット対象とする。
③git commitでファイルをコミットする。
④git remote add originでGitHubで作成したリポジトリと連携する。
⑤git fetchで差分を取り込む
⑥git mergeでローカルリポジトリとリモートリポジトリを合体させる。
⑦git pushでリモートリポジトリにコミットする。