Gitまとめ【備忘録】

初めまして、Taku3と言います。
最近Gitについて学んでいるので、備忘録兼ねてアウトプットしていきます。

# Gitとは

`書いたソースコードをバージョンごとにまとめるツール`のこと。
Git、GitHubとか色々あるけど、Git(ローカルのツール)で管理しているコードをGitHub(Webサービス)にアップロードできます。これらを使うメリットとしては、
- ソースコードのバージョン管理
- 開発チーム内(またはチーム外)での共有

などが挙げられます。

## GitやGitHubでのバージョン管理について

GitやGitHubでは以下の特徴があります。
1. スナップショットの保存
2. 過去バージョンの参照

1について、まずデータの保存方法として、「そのデータを丸ごと保存する」か、「データ内に前回からどのような変更点が生じたかを保存する」かの二択があると思います。
Gitでは前者、つまり丸ごと(スナップショットとして)保存しており、前回アップロード時との差分を計算したりしないのでその分早いです（確かそう）。

2について、Gitではアップロード(以後、コミット)されたデータに対して、前回コミットしたデータが親コミットとして紐づけられています。

以下画像は、バージョン1からバージョン2,3へと更新されるにつれ、ファイルAがファイルA'に更新されたり、ファイルCがファイルC'、ファイルC''に更新されるという例です。

GitやGitHubでは、バージョン3からバージョン2に遡れることができ、そこから更にバージョン１に遡ることもできます。
バージョン3時点では、ファイルAはファイルA'となっていますが、過去のファイルAを再び参照できるというわけです。
![無題のプレゼンテーション (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2770820/c2c76a7a-6f1b-b28a-2fb4-f4b97c7bd9e8.jpeg)

Gitなどを使わずに共有フォルダなどでバージョン管理した場合、色んなバージョンが同フォルダ内で混在したり、そもそも過去のバージョンが残っていなかったりも考えうるので、GitやGitHubで管理する意味は大いにありますね。

## 基本コマンド
#### ステージにアップ&ローカルリポジトリにコミット
```
git add <ファイル名>(. とすると今のディレクトリの全ファイル)
↓
git commit -m "<message>"
```
今作業しているワークツリーで変更したファイルに対して、まずステージにアップして反映の準備をする必要があります。これがgit addです。
その後、git commitするとローカルリポジトリに反映完了となります。

なお``-a``オプションを付けてcommitすることでgit addコマンドを省略できます。
```
git commit -a -m "<メッセージ>"
```

#### GitHubへのプッシュ
```
git remote add <リモート名> <URL>
↓
git push <上記のリモート名> <ブランチ名>
```

```ruby:例
$ git remote add origin https://github.com/<GitHubアカウント名>/<リポジトリ名>.git
$ git push -u origin master
```

ブランチは、複数人で並行して開発するためにの機能です。親子関係で連なるコミットに対して、どのコミットファイルを指しているかというポインタのことです。
あるコミットファイルAからチーム内の何人かでブランチを分けて修正することで、コミットファイルAは安定して稼働できるファイルとして残しつつ、新機能の開発や改修を各々のコミットファイルでできるというわけです。（上手く改修などできれば、元のコミットファイルAとマージなどして更新します）
またgit push時に-uをつけることで、次からgit pushだけで同じリポジトリにプッシュできます。


#### ファイルの状態確認
```
git status
```
ファイルが変更されているか、git add済みかなどが確認できます。
都度、変更の状況を確認しつつgit add,commitしましょう。

#### ワークツリーの変更取り消し
```
git checkout -- <ファイルorディレクトリ名>
```
git checkout <ブランチ名>（ブランチの切り替え）と混ざるので--を付けた方が良いです。

#### ステージに追加した変更の取り消し
```
git reset HEAD <ファイル名orディレクトリ名>
```
ローカルリポジトリの最新情報（HEAD）でステージを上書きする(=元に戻す)。

#### 直前のコミットのやり直し
```
git commit --amend
```
何かのファイルをコミット後(1)、再修正などが必要な場合を想定する。コミット後、ワークツリーで修正→ステージにgit addし、その次にgit commit --amendをすることで(1)のコミット結果を上書きできます。コミットファイル無駄に増えなくて良いです。

※リモートリポジトリにpush済みの場合はやってはダメ
とあるファイルver3をコミット後、Aさんがver3のまま中身を修正するとします。コミット直後～Aさん修正の間にBさんがpullして修正したら、A、B間でコミットファイルの修正履歴が矛盾してしまいます。

#### 差分の確認
```
git diff
```
ワークツリーとステージ間の差分確認。
--stagedをつけるとステージとローカルリポジトリ間の差分を見れます。

#### ファイル削除
```
git rm <ファイル名>
または
git rm -r <ディレクトリ名> 
```
Linuxコマンドと同じっぽい。
基本的にワークツリー、ステージ、ローカルリポジトリで削除されますが、--cachedをつけるとローカルリポジトリだけ削除になります。

#### ファイルの移動
```
git mv
```

#### エイリアス設定
```
git config --global alias.<エイリアス名> <コマンド名>
```
--globalを付けるとPC全体での設定になります。

#### ログ確認
```
git log
git log --oneline
git log -n <num>
など
```

#### リモート情報表示
```
git remote
git remote -v(URL表示)
git remote show <リモート名>
```
git remote showは上二つよりも詳細に表示される。

#### GitHubから情報を取得(fetch)
```
git fetch <リモート名>
git merge origin/main
```
git fetchでorigin/mainなどのローカルのブランチに保存される。
git mergeすることでワークツリーにも反映できる。
少し話がずれますが、mergeにはFast ForwardとAuto Mergeが存在します。

![【Git】mergeの違い (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2770820/5b8683e3-48ad-a13f-6914-94f442153534.jpeg)

Fast Forwordは次のコミットファイルにブランチ切り替えることです。
Auto Mergeは複数のコミットファイルをマージし新しいコミットファイルを作成、それを指すようにブランチが更新されます。（）

#### GitHubから情報を取得(pull)
```
git pull <リモート名> <ローカルのブランチ名>
```
pullは取得するデータのあるブランチとは関係なく、自分のいるブランチに保存されるので注意。
(例:mainブランチでfeatureブランチをpullした場合、mainに保存される)

#### リモート名変更
```
git remote rename <旧リモート名> <新リモート名>
```

#### リモート名削除
```
git remote rm <リモート名>
```

#### ブランチの切り替え
```
git checkout <ブランチ名>
```

#### ブランチの新規作成
```
git branch <ブランチ名>
```
これだけでは切り替わらないので、作成後git checkoutしてください。
又は以下コマンドでブランチ作成＆切り替えができます。

```
git checkout -b <作成するブランチ名>
```

#### ブランチ一覧表示
```
git branch (-a)
```
-a付きで全権表示

#### ブランチの指す内容の確認
```
git log --oneline --decorate
```

#### 現在のブランチ名変更
```
git branch -m <新しいブランチ名>
```
#### ブランチの削除
```
git branch -d <ブランチ名>
```
mainにマージされていないファイルなどがあると削除されない。
強制削除するには-dを-Dに変更して実行する。

#### リベース
```
git rebase <ブランチ名>
```
リベースはコミットの履歴を整えるために使う機能です。

親コミットの内容がローカルで変わってしまいリモートと矛盾が生じる為、git pushしたコミットはリベースしてはいけません。
以下はリベースのイメージです。
![【Git】mergeの違い (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2770820/bbb5aa27-d0d0-34fd-5491-6a32216c7739.jpeg)
マージと異なり、元々いた自分の親ブランチを削除して、別の親ブランチの子ブランチとして乗り換えています。

またリベースの他の使い方として、複数のコミットを一度に修正することも挙げられます。
```
git rebase -i HEAD~3
```
rebaseすると直近3つまでのコミットに対して以下のような情報がエディタで表示されます。
```
pick kei43bd commit 1
pick 83ugj32 commit 2
pick 3i2jed4 commit 3
```
pickの部分をeditに変え、
```
git commit --amend
```
で再度やり直したりできます。
上記で複数editに変更した場合、
```
git rebase --continue
```
で次のコミットの変更コマンドが打てるようになります。

#### タグの表示
```
git tag
```

#### 注釈付きタグの作成
```
git tag -a "<タグ名>" -m "<メッセージ>"
```

#### 軽量版タグの作成
```
git tag "<タグ名>"
```

#### 昔のコミットに後からタグ付け
```
git tag "<タグ名>" <コミット名>
```

#### タグのデータ表示
```
git show "<タグ名>"
```

なお、タグは別途pushが必要なので注意してください。
```
git push <リモート名> <タグ名>
```

#### 一次退避
```
git stash (save)
```
saveは省略可

#### 退避の確認
```
git stash list
```

#### 退避から復元
```
git stash apply
```
ステージの状況も復元するには、
```
git stash apply --index
```

#### 特定の退避の復元
```
git stash apply stash@{x}
```
xにはstashの順番が入っており、git stash listで確認できます。

#### 最新の退避の削除
```
git stash drop
```

#### 特定の退避の削除
```
git stash drop stash@{x}
```

#### 退避の全削除
```
git stash clear
```

知識としては学んだものの定着はまだまだなので、実践あるのみですね。
また追加で知識を学び次第更新していきます。