Gitのチュートリアル 演習 1

# リポジトリ作成から基本的なコミットの方法
gitをコマンドラインで利用するチュートリアル的な演習の第1部です。[^0]
[^0]: 4部構成の予定です。

この文書では`git init`、`git status`、`git add`などを使った単純なコミットまでの演習、ファイルの状態やワークフローについての解説などを取り扱っています。

この文書ではgitをコマンドラインで利用するための環境構築については触れていません。([ご参考までに私の環境構築ログ](https://qiita.com/ "準備中 qiita内の記事"))

:::note info
参考サイト
* [gitドキュメント](https://git-scm.com/book/ja/v2 "Pro Git 2nd Edition(2014)") (原文は[こちら](https://git-scm.com/book/en/v2))
pdfやepub形式のダウンロードもあります。日本語に翻訳されています。
* [Git ユーザマニュアル (バージョン 1.5.3 以降用)](https://img.atwiki.jp/git_jp/pub/Documentation.ja/user-manual.html)
日本語訳されたユーザマニュアル
* [Git入門編１：Gitの基本操作を身に付けよう](https://paiza.jp/works/git/primer/beginner-git1 "paizaラーニング")
 paiza提供の講座。2講座無料視聴できます。初期設定からripositoryを作るまでの流れが動画で説明されています。
仮想ターミナルが用意されているため環境構築なしにgitやshellコマンドを試すことができます。
* [GitHub Git チートシート](https://training.github.com/downloads/ja/github-git-cheat-sheet/)
クイックリファレンスのようなまとめシート。
* [Chapter 12. 付録Ａ：Git Quick Reference](https://img.atwiki.jp/git_jp/pub/Documentation.ja/user-manual.html#git-quick-start)
Git ユーザマニュアル (バージョン 1.5.3 以降用)に掲載されているクイックリファレンス。
:::

# [演習1] ユーザ識別情報を登録する 
:::note info
参考
[1.6 Getting Started - First-Time Git Setup](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup "1.6 Getting Started - First-Time Git Setup")の **Your Identity** ([日本語訳](https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-%E6%9C%80%E5%88%9D%E3%81%AEGit%E3%81%AE%E6%A7%8B%E6%88%90))
[GitHub Git チートシート](https://training.github.com/downloads/ja/github-git-cheat-sheet/)の **ツールの設定** 
:::

gitを使い始める際に一番最初に行う設定です。
commitなどを行ったときにAuthorとして記録される情報を登録します。
~~~shell:command
~$ git config --global user.name "KaoriTakinami"
~$ git config --global user.email "61788460+KaoriKoba@users.noreply.github.com"
~~~

:::note warn
githubを利用されている方へのTips

もし、将来的にローカルリポジトリを github へ移行したい場合は、ここで指定するメールアドレスをgithubで用意されている公開用のメールアドレスにする事をお勧めします。

プライベートなアドレスを指定した場合、githubへの remote pushの際に "プライベートなメールアドレスが公開されてしまう" という旨の警告が出されエラーとなります。

プライベートなメールアドレスを利用してコミットなどのlogを残したリポジトリをgithubへpushする場合はgithub側のメール設定で 
> Block command line pushes that expose my email

をオフにする必要があります。

※ チュートリアル演習1～4にはローカルリポジトリからgithubへpushする内容は含みませんので、演習を行うだけであればどのようなアドレスを設定しても問題はありません。
:::


# [演習2] リポジトリを作ろう

まず、プロジェクトのフォルダを作成し、その中にgitのローカルリポジトリを作成します。

:::note info
参考
[Git入門編１：＃02:リポジトリを作ろう(paizaラーニング)](https://paiza.jp/works/git/primer/beginner-git1/17001 "paizaラーニング")
:::

## [演習2-1] 演習用の準備・プロジェクト用ディレクトリの作成 [^1]
[^1]: ディレクトリ名などはご自由に変更してください
:::note info
command コードブロック内に表示しているコマンドプロンプトは
 `カレントディレクトリ$` 
です。 
:::
演習用のディレクトリを用意します。`mkdir git_prac`
そのディレクトリの中にプロジェクト用のディレクトリを用意します。`mkdir proj`
さらにその下に今回のチュートリアル用のディレクトリを作成します。`mkdir tutorial`[^2]

~~~shell:command
~$ mkdir git_prac
~$ cd git_prac
~/git_prac$ mkdir proj
~/git_prac$ cd proj
~/git_prac/proj$ mkdir tutorial
~/git_prac/proj$ cd tutorial
~~~

[^2]:後に続くチュートリアル演習でprojの下に複数のローカルリポジトリを作成するため、このようなディレクトリ構成にしています。

## [演習2-2] リポジトリを作成する
:::note info
参考
 [2.1 Git Basics - Getting a Git Repository](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository) ([日本語訳](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-Git-%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E5%8F%96%E5%BE%97))
:::
作成したtutorialディレクトリ内で`git init`をすることで、カレントディレクトリ内のファイルがgitの管理下におかれる準備ができます。
具体的にはカレントディレクトリ内に .git という名のサブディレクトリが作成されます。
~~~shell:command
~/git_prac/proj/tutorial$ git init
Initialized empty Git repository in /home/user/git_practice/project/.git/
~~~

:::note warn
この時点でカレントディレクトリ内にファイルがあってもリポジトリに登録(コミットやステージングなど)されたりはしません。
:::

# [演習3] 状態について知ろう

リポジトリにファイルを登録する前にgitの世界での管理のための、ファイルの状態と、３つの状態(ワークフロー)と、その状態を確認するコマンド`git status`を紹介します。

この項目は長く難解な説明になっています。

`git status`で表示される内容を理解するには必要な情報ですが、この項目を飛ばして **[[演習3-2] リポジトリの状態を確認しよう](https://qiita.com/drafts/9980dc6b52451a99e197/edit#%E6%BC%94%E7%BF%923-2-%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E7%8A%B6%E6%85%8B%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%97%E3%82%88%E3%81%86)** 以降を進め、適宜この項目を参照していただいても構いません。
 
## [演習3-1] gitの管理下でのファイルの状態とgitのワークフローについて

ファイルの状態や、編集から履歴登録までのワークフローなどを解説します。

#### gitのファイルの状態
:::note info
参考
 [2.2 Git Basics - Recording Changes to the Repository](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository) ([日本語訳](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E5%A4%89%E6%9B%B4%E5%86%85%E5%AE%B9%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%B8%E3%81%AE%E8%A8%98%E9%8C%B2))
この項目の日本語訳は少し難解なのでよくわからない場合は[原文](https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F)を参照したほうが理解しやすいかもしれません。
<details><summary>難解かもしれない部分</summary>
<a href="https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E5%9F%BA%E6%9C%AC">1.3 使い始める - Gitの基本</a>の`三つの状態`の項
 <blockquote> 
    Gitは、ファイルが帰属する、`コミット済、修正済、ステージ済`の、三つの主要な状態を持ちます。
 </blockquote> 
この訳は挿絵と語順があっていないので理解の妨げとなるかもしれません。<a href="https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository">原文</a>もご覧ください。
 <blockquote> 
    Git has three main states that your files can reside in: `modified, staged, and committed`:
 </blockquote> 
</details>
:::

上記参考文献の要約
> リポジトリを作成したりチェックアウトしたディレクトリ内のファイルは2つのどちらかになっている。
> - **tracked (追跡されている)**
> - **untracked (追跡されてない)**
> 
> **tracked (追跡されている)** ファイルがリポジトリで履歴管理対象のファイル。
>
> **tracked(追跡されている)** ファイルは以下の状態になる。
> - **unmodified (変更されていない)**
> - **modified (変更されている)**
> - **staged (ステージされている)**
> ![ファイルの状態遷移図](https://git-scm.com/book/en/v2/images/lifecycle.png "ファイルの状態")

gitで履歴管理を始める時は **untracked** のファイルを **tracked** にする事から始まります。

:::note info 
管理されていないファイルをリポジトリに登録する
1. まず、**untracked (追跡されてない)** ファイルを`git add`して **staged (ステージされている)** にします。[^3] 
1. コミット`git commit`する。コミットすることでそのファイルの変更履歴がリポジトリに記録されます。
:::

[^3]:ステージングといいます

**untracked** のファイルを **tracked** にできたら、その後のファイルの状態は大抵以下のような流れなります。上記の図を参照しながらご確認ください。

:::note info
管理されているファイルを更新したときのファイルの状態変化
1. **unmodified** (変更されていない＝リポジトリに登録されている内容と一致している) 
1. 編集すると **modified (変更されている)** の状態になります。
1. `git add` を行い **staged (ステージされている)** の状態へ[^3] 
1. コミット`git commit`して変更履歴を記録します。
1. コミットを終えたファイルは **unmodified** になり1の状態へ戻ります。
:::

#### リポジトリにコミットするまでのワークフロー(各段階の呼称) 

:::note info
参考
 [1.3 Getting Started - What is Git?](https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F) ([日本語訳](https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E5%9F%BA%E6%9C%AC))
:::

上記参考文献の要約
> gitには主に3つの状態がある
> - **modified (修正済)** -- ファイルを変更したが、まだデータベースにコミットしていない状態
> - **staged (ステージ済)** -- 変更されたファイルの現在のバージョンを次のコミットのスナップショットに含めることをマークした状態(インデックス)
> - **committed (コミット済)** -- データが安全にローカルデータベースに保存された状態
>
> この状態はgitの3つのセクションになる
> - **working tree (ワーキングツリー)** -- プロジェクトがチェックアウトされた状態
> - **staging area (ステージングエリア)** -- Gitディレクトリに含まれるファイルで、次のコミットに含まれる情報を格納
> - **Git directory (Gitディレクトリ)** -- プロジェクトのメタデータとオブジェクトデータベースを格納するGitの最も重要な部分
> ![gitのワークフロー解説図](https://git-scm.com/book/en/v2/images/areas.png "gitのワークフロー")

基本的なGitのワークフローは次のようになります。上記の図を参照しながらご確認ください。

:::note info
基本的なGitのワークフロー
1. **ワーキングツリー** [^4] 内のファイルを編集(変更)。
1. 次のコミットに含める変更済みファイルを選択してステージング`git add`。これにより、**ステージングエリア** には選択された変更のみが追加されます。
1. コミット`git commit`を行う。コミットすることでステージングエリアのファイルがそのスナップショットとして **.gitディレクトリ(リポジトリ)** に保存されます。
:::

[^4]: `git init` や `git checkout` を行ったディレクトリの事です。つまり .git ディレクトリが格納されているディレクトリです。

## [演習3-2] リポジトリの状態を確認しよう

次に紹介するコマンドはワーキングツリー内のファイルがどんな状態にあるのかを確認できるコマンド`git sattus`です。

ワーキングツリーとは簡単に言うと `git init` や `git checkout` を行ったディレクトリの事です。つまり .git ディレクトリが格納されているディレクトリです。

`git init` したばかりのディレクトリで`git status`します。
~~~shell:command
~/git_prac/proj/tutorial$ git status
On branch master
nothing to commit, working tree clean
~~~

以降の演習では適宜`git status`を使い、どのように状態が変化するかを説明しながらすすめます。

# [演習4] リポジトリにファイルを登録しよう(ステージング)

登録するファイルを用意します。
~~~shell:command
~/git_prac/proj/tutorial$ echo "this is a test." >> test.txt
~~~
状態を確認`git status`するとtest.txtがUntracked file[^5]であることがわかります。
`git status`で表示されるメッセージでも **コミットに加えるものはないけどトラックしていないファイルがある**と教えてくれます。
~~~shell:command
~/git_prac/proj/tutorial$ git status
On branch master
No commits yet
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test.txt
nothing added to commit but untracked files present (use "git add" to track)
~~~

[^5]:状態を示す言葉の意味が不明な場合は[状態について知ろう](https://qiita.com/drafts/9980dc6b52451a99e197/edit#%E6%BC%94%E7%BF%923-%E7%8A%B6%E6%85%8B%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E7%9F%A5%E3%82%8D%E3%81%86)を振り返ってみてください。

コミットに含めるためにtset.txtをステージングします。ステージングするコマンドは`git add` です。

~~~shell:command
~/git_prac/proj/tutorial$ git add test.txt
~~~
状態を確認`git status`してみると新しいファイルがステージングされたことがわかります。
~~~shell:command
~/git_prac/proj/tutorial$ git status
On branch master
No commits yet
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   test.txt
~~~

# [演習5] リポジトリにファイルを登録しよう(コミット)
コミット`git commit`は、変更履歴をリポジトリに記録するためのコマンドです。

コミットする際には変更に関する簡単な説明を付加します。メッセージといいます。

メッセージは`-m` で指定できます。プロジェクト最初のコミットメッセージは **"Initial commit"** とし、プロジェクトの概要などを記すようです。

~~~shell:command
~/git_prac/proj/tutorial$ git commit -m "Initial commit"
[master (root-commit) 1866c44] Initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt
~~~
状態を確認してみましょう
~~~shell:command
~/git_prac/proj/tutorial$ git status
On branch master
nothing to commit, working tree clean
~~~
更新されるものもなく、ワーキングツリーはきれいな状態のようです。

リポジトリに登録した履歴を確認するコマンドに`git log`があります。
~~~shell:command
~/git_prac/proj/tutorial$ git log
Author: KaoriTakinami <KaoriTakinami@foo.bar>
Date:   Thu Apr 27 19:23:43 2023 +0900

    Initial commit
~~~
[[演習1] ユーザ識別情報を登録する](https://qiita.com/drafts/9980dc6b52451a99e197/edit#%E6%BC%94%E7%BF%921-%E3%83%A6%E3%83%BC%E3%82%B6%E8%AD%98%E5%88%A5%E6%83%85%E5%A0%B1%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B) で登録した情報でコミットされていることが確認できます。

# [演習6] ファイルを更新してコミットする
tracked のファイル(test.txt)を更新してコミットしましょう。

今回はステージング`git add`を省略してコミットする方法`git commit -a`を紹介します。
~~~shell:command
~/git_prac/proj/tutorial$ echo "plz ignore." >> test.txt
~/git_prac/proj/tutorial$ git status
On branch master
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:   test.txt
no changes added to commit (use "git add" and/or "git commit -a")
~~~
~~~shell:command
~/git_prac/proj/tutorial$ git commit -a -m "追加の変更"
[master caf0c0b] 追加の変更
 1 file changed, 1 insertion(+)
~~~

# [演習7] プロジェクトに新しくファイルを追加しよう
新しくファイルを追加してみましょう。
tmpという名前のファイルを作成します。`touch tmp`
~~~shell:command
~/git_prac/proj/tutorial$ touch tmp
~/git_prac/proj/tutorial$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        tmp

nothing added to commit but untracked files present (use "git add" to track)
~~~

コミットの際に、`git add`を省略してステージングを行う方法`git commit -a`を[演習6](https://qiita.com/drafts/9980dc6b52451a99e197/edit#%E6%BC%94%E7%BF%926-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E6%9B%B4%E6%96%B0%E3%81%97%E3%81%A6%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%99%E3%82%8B)で紹介しましたが、**untrackedのファイルは自動的にステージングしない** ので、新しいファイルを登録する場合は`git add`を省略できません。

新しくファイルを追加する場合は`git add`した後、`git commit`します。
~~~shell:command
~/git_prac/proj/tutorial$ git add tmp
~/git_prac/proj/tutorial$ git commit -m "temporary file の追加"
[master db39370] temporary file の追加
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 tmp
~~~

一度追加した後は、`git add`を省略して`git commit -a`を利用することができます。

-------
ここまでの内容で **[[演習3-1] gitの管理下でのファイルの状態とgitのワークフローについて](https://qiita.com/drafts/9980dc6b52451a99e197/edit#%E6%BC%94%E7%BF%923-1-git%E3%81%AE%E7%AE%A1%E7%90%86%E4%B8%8B%E3%81%A7%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E7%8A%B6%E6%85%8B%E3%81%A8git%E3%81%AE%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)** で紹介した**ファイルの状態**や**３つのセクション**について具体的な利用例を紹介しました。

次の[Gitのチュートリアル演習 2]()ではステージングが存在する理由を実感できるような演習になればと思います。