gitで取ってきてさかのぼろう入門


シリーズのトップは↓こちら

https://qiita.com/every-month/items/a6a9f481ac31eb695d25

前回の記事は↓こちら

https://qiita.com/every-month/items/84a5dc110fc06850fd3c

たまたまプライベートで人にAppRouterなNext.jsを叩き込む過程でgitの使い方を叩き込む機会がありまして、せっかくなので再びこの場をお借りしていっしょに復習します。

## 前回までのポイント（再掲）（抜粋）

- `cd`
    - フォルダの中に入る
- git clone ほしいやつ
- gitで取ってきたNext.jsのプロジェクトにはnpm i

## 今回のポイント

- `git checkout HEAD^`で直前のフォルダの状態を取ってくる
    - `HEAD^`が今のフォルダの直前の状態
    - これ何回も実行するとどんどん前に戻れる
- `git log`で過去の作業の記録が見れる
    - この画面は`q`を入力して抜けれる
- たとえば`git checkout a2b8a65`のようにしてさかのぼることもできる

## 今回やることの趣旨

前々回くらいから↓のGitHubに記事の通りに作った例を置いていましたが途中から復習する時に使えるよう、さかのぼり方を紹介します。

https://github.com/tenshoku-2024/typescript-oni-spartan-dojo

## 復習`git clone`

以前こんなコマンドを実行して、Next.jsのフォルダを取ってきました。

```bash:以前ターミナルに入力した
git clone https://github.com/tenshoku-2024/typescript-oni-spartan-dojo
```

↑のコマンドを実行すると↓だいたいこんな出力が出ます。

```:ターミナルに出た出力
Cloning into 'typescript-oni-spartan-dojo'...
remote: Enumerating objects: 52, done.
remote: Counting objects: 100% (52/52), done.
remote: Compressing objects: 100% (29/29), done.
remote: Total 52 (delta 14), reused 52 (delta 14), pack-reused 0
Receiving objects: 100% (52/52), 63.05 KiB | 2.10 MiB/s, done.
Resolving deltas: 100% (14/14), done.
```

ちなみに２回実行すると失敗します。これは取ってくるフォルダの名前がかぶってしまうからです。

```:ターミナルに出た出力
fatal: destination path 'typescript-oni-spartan-dojo' already exists and is not an empty directory.
```

これを回避する方法もあります（記事の下の方で紹介）

そんなこんなで`git clone`したら、そのフォルダの中に移動します。

```bash:ターミナルに入力
cd typescript-oni-spartan-dojo
```

## さかのぼる：`git checkout`してみよう

今回は最新のフォルダの直前の状態のフォルダがほしいので、↓こんなコマンドを実行します。

```bash:ターミナルで実行
git checkout HEAD^
```

すると↓こんな出力が出ます。

```:ターミナルに出た出力
Note: switching to 'HEAD^'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 2b7a926 add new page
```

これでフォルダの中の状態が最新のフォルダの直前の状態になりました。

この`HEAD^`というのは、今のフォルダの状態の直前という意味なので、`git checkout HEAD^`を何回も実行すると、どんどん前の状態に戻れます。（戻っちゃいます）

## このフォルダのNext.jsを動かす前に

このフォルダの状態の時点で必要なパッケージを取ってきます。

```bash:ターミナルに入力
npm i
```

↑これの後でNext.jsを↓これで動かすのがおすすめです。

```bash:ターミナルに入力
npm run dev
```

## 記録を見る

↓こんなコマンドを実行すると過去に残された作業の記録が見れます。

```bash:ターミナルで実行
git log
```

↑のコマンドを実行すると↓こんな画面に入れます。

```:
commit 2b7a92690756169f9a944d1558a6b47d9a1d2a5d (HEAD)
Author: nobody <nobody@localhost.localdomain>
Date:   Thu Jan 1 00:00:00 1970 +0000

    add new page

commit 434241ad2b52e752776a339d3d1e7b2b9ddbec10
Author: nobody <nobody@localhost.localdomain>
Date:   Thu Jan 1 00:00:00 1970 +0000

    add images

commit a71d5ee4962f4ddda55e88fbf527bebb81c12e8c
Author: nobody <nobody@localhost.localdomain>
Date:   Thu Jan 1 00:00:00 1970 +0000

    set colors

commit a2b8a6542cc3bcbd3b96f19f528d77a16aa77cee
Author: nobody <nobody@localhost.localdomain>
Date:   Thu Jan 1 00:00:00 1970 +0000

    do hello world
:
```

今ならこんな感じになっています。(HEAD)と書いてあるのが（正確には、さらにフォルダを直接変更していない場合に限って）「現在はフォルダがこの時点のものになってます」の意味です。

この画面を抜けるときは`q`と入力します。

例えば`do hello world`の上の、この`commit`と書いてあるところの、`a2b8a6542cc3bcbd3b96f19f528d77a16aa77cee`という数字とアルファベットの羅列が、過去に記録した作業の記録のIDみたいなものです。（正確にはハッシュですが）

## もっと`git checkout`の話

先程の`git checkout HEAD^`での`HEAD^`の代わりにこの数字とアルファベットの羅列の左から７桁くらいをつかうこともできます。

たとえば、

```bash:ターミナル入力
git checkout a2b8a65
```

とすること`do hello world`のフォルダを取ってくることができます。

## 今回のポイント（再掲）

- `git checkout HEAD^`で直前のフォルダの状態を取ってくる
    - `HEAD^`が今のフォルダの直前の状態
    - これ何回も実行するとどんどん前に戻れる
- `git log`で過去の作業の記録が見れる
    - この画面は`q`を入力して抜けれる
- たとえば`git checkout a2b8a65`のようにしてさかのぼることもできる

## おまけ：`git clone`でフォルダの名前がかぶらないためには

例えばこのように、

```bash:以前ターミナルに入力した
git clone https://github.com/tenshoku-2024/typescript-oni-spartan-dojo hontouha-yasasii-typescript-dojo
```

のように`git clone リポジトリ 今から取ってくる先のフォルダの名前`とすることでかぶらないような名前を指定することもできます。