git (git hub)についての学習アウトプット

## ブランチとは

ブランチとは履歴の流れを分岐して記録していくもの。分岐したブランチは他のブランチの影響を受けないため複数の変更を同時に進めていくことができる。

分岐したブランチはmerge（合流）することで一つのブランチにまとめ直すことができる。

## ブランチ運用の流れ

- メインブランチから作業専用のブランチを作成する（checkout -b “ブランチ名”で作成可能）
- 作業が終わり次第自分のブランチをメインのブランチに取り込む（push merge）また、作業単位で履歴を残す（commit）ことで、問題が発生した場合に原因となる変更箇所の調査や対策を行うことができる。

## masterブランチ

リポジトリに最初のcommitを行うとgitはmasterという名前のブランチを作成する（現在はmain）

ここからブランチを切って開発作業をする。

## 統合ブランチ

後述するトピックブランチの分岐元となるブランチ。そのため安定した状態が求められる。

CIツールのテストなどはこのブランチで行う（うちではSTがそれにあたる？）

## トピックブランチ

トピックブランチとは、機能追加やバグ修正といった課題に関する作業を行うためのブランチ。

課題の数だけトピックブランチが作成されることになる。

統合ブランチからトピックブランチを作成し作業が完了したら統合ブランチに取り込むことになる。

## ブランチの切り替え

masterブランチから、トピックブランチに切り替えるには’checkout’コマンドを使う

```md
git checkout ブランチ名　 <!--既存のブランチに切り替える-->
```

または、

```md
git checkout -b ブランチ名 <!-- ブランチの作成と切り替えを同時に行う -->
```

新規にブランチだけを作成する場合

```md
git branch ブランチ名 <!-- ブランチは作成されるが、checkoutはされない -->
```

とする

## HEAD

HEADとは現在使用しているブランチの先頭を表す名前。デフォルトではmasterブランチの先頭を表す。

## stash

通常コミットしていない内容や新く追加したファイルがインデックスやワーキングツリーに残ったままで別のブランチにcheckoutするとその変更は移動したブランチに反映される。

ただ、移動さきのブランチで同じファイルを編集していた場合、checkoutすることができない。

このような場合、変更をcommitするか、stashを使い、一時的に変更内容を退避させてからcheckoutする。

```md
git stash <!-- コマンド -->
```

## ブランチの統合

ブランチの統合にはmergeとrebaseの二種類がある

## merge

あるブランチをmasterブランチにmergeする場合、masterブランチの状態が以前から変更されていなければmergeを行うのは容易。その場合のmergeを’fast-forward’(早送り)mergeと呼ぶ。

もし、mergeを行うときに、masterブランチの状態が、checkoutした時と変わっているときはmasterブランチとトピックブランチの両方のcomiitを取り込んだマージコミットが作成され、masterブランチの先頭はそのcommitに移動する。

※mergeの’non fast-forward’というオプションを指定することで、fast-forwardマージが可能な場合でもマージコミットを作成したmergeが可能になる。

## rebase

ブランチの変更記録を一本化する方法。

mergeではトピックブランチの変更履歴（のcommit）はmasterブランチには取り込まれず、トピックブランチを取り込んだ履歴が残る形になるが、rebaseではトピックブランチを取り込む時、その時のHEADの後ろにトピックブランチの全てのcommit履歴が統合される。

この時、masterの先頭はrebaseする前の状態と変わらないので、rebase後はmergeしてトピックブランチの変更を取り込まなければいけない。

## 変更したファイルをインデックスに登録する（commit前のスタンバイ状態）

```md
git add ファイル名
```

## ブランチを削除する

```md
git branch -d ブランチ名
```

## 現在存在するブランチを確認する

```md
git branch
```

## リモートリポジトリの変更履歴を取得する

```md
git pull ブランチ名
```

## リモートリポジトリの内容を確認する

リモートリポジトリの変更を取り込む前に内容だけを確認したい場合は

```md
git fetch origin master
```

とする。内容は’FETCH_HEAD’という名前でcheckoutして確認することができる。

その後、そのまま内容を取り込みたければ、git mergeで変更を取り込む。

‘git pull’はこれら一連の作業を一気に行うコマンド。

## ローカルリポジトリをリモートにpushする

```md
git push ブランチ名
```

## conflictを解消する

別々のトピックブランチで同じファイルを編集している場合

```rb
<<<<<<< HEAD
puts 'hello'
=======
puts 'おはようございます'
>>>>>>> # mergeしたいブランチ
```

mergeしたいブランチとは別のブランチで同じファイルを編集しており、それぞれの変更が競合(conflict)してしまっている。

これを解消（今回は両方の変更を取り込む）するには

```ruby
puts 'hello'
puts 'おはようございます'
```

と、残したい変更箇所を残せばOK。そして、conflictを解消したことを記録したいので解消後のファイルを改めてcommitしてmergeする。このようなmerge をnon fast-forward mergeという。

## rebase時のconflictを解消する

ファイルを変更したブランチをrebaseでmasterに取り込もうとする時も、conflictが発生する。

```ruby
<<<<<<< HEAD # 同じようにconflictが発生するので同じように修正する
puts 'hello'
=======
puts 'おはようございます'
>>>>>>> # mergeしたいブランチ
```

修正後

```ruby
puts 'hello'
puts 'おはようございます'
```

rebaseの場合はconflictを修正した後は、commitではなくrebaseコマンドに —continueオプションを指定して実行する。

もし、rebase自体を取りけす場合 —abortオプションを指定して取り消しを行う。

git rebase —continue後はmasterブランチにcheckoutし、git merge ブランチ名とし、masterに変更を取り込む。

## タグをつけてcommitを参照しやすくする

タグとは、後々commitを参照しやすくするためにつけるもの。

軽量タグと注釈付きタグがある。

### 軽量タグ

- 名前だけをつけられる

### 注釈付きタグ

- 名前をつけられる
- コメントをつけられる
- 署名をつけられる

本番にリリリースするときは注釈付きタグを使いコメントや署名を追加する。軽量タグはローカルで一時的に使用する使いすてなどに使用する。

## 軽量タグを追加する

現在のHEADが示しているcommitにタグをつける

```md
git tag test <!-- testというタグが今いるリポジトリの最新のcommitにつけられる -->
```

```md
git tag <!-- つけられているタグの一覧を取得できる -->
```

```md
git log --decorate <!-- タグ情報を含めて履歴を確認することができる -->
```

## 注釈付きタグを追加する

```md
git tag -a タグ名
```

とするとコメントを入力できるエディタが起動するので、

```md
git tag -am ’これはテストタグです’ test
```

とすると、’test’というタグに「これはテストです」という注釈（コメント）をつけることができる。

## タグを削除する
```md
git tag -d タグ名
```

とする。

## 直前のcommitメッセージを修正する

```md
git commit --amend -m "このコメントに書き換える"
```

## 過去のcommitを打ち消す

公開済み（他の人も取り込んでいる）commitは勝手に削除することができない。（自分の手元では削除されても他の人の手元では削除されず履歴がおかしくなってしまうため）

その場合は、revertで過去のcommitの内容を打ち消すコミットを作る。

＊railsのマイグレーションファイルのような考え方。過去に作ったマイグレーションファイルを削除するとrails db:migrationを実行した時に整合性が取れなくなりマイグレーションできなくなってしまうためもし過去にマイグレーションしたファイルの内容を変更したいときは、その内容を打ち消すマイグレーションファイルを作成しrails db:migrateする。

```md
git revert <commit ID> <!-- このIDはgit logコマンドを打つと表示されるID -->
```

このコマンドを実行すると、commitメッセージを変更するエディタが起動する。

## commitを削除する

一度commitした内容を削除するときは

```md
git reset
```

コマンドを実行する。

オプションを指定することで、resetを影響範囲を変えることができる。

```md
# 直前のコミットをなかったことにする
git reset --soft HEAD^
```

```md
# 直前のコミットを取り消し
git reset --hard HEAD^
```

```md
# コミット後の変更を全部消したい
git reset --hard HEAD
```

```md
# addを取り消したい
git reset --mixed HEAD
```

```md
# git resetをなかったことにする
git reset --hard ORIG_HEAD
```

## commitを抜き取る

別のブランチから指定したcommitをコピーして、現在のブランチに取り込むことができる。

```md
git cherry-pick <commit ID>  <!-- git log で事前に取り込みたいcommitのIDを確認しておく -->
```

## revase -i オプション

```md
git rebase -i HEAD~~ # テキストエディタが起動しHEADから二つ前のcommitが表示される
```

```md
pick <commit ID> commitメッセージ # HEADから二つ前のcommit
pick <commit ID> commitメッセージ # HEADから一つ前のcommit この行のpickをsquashに変更し保存する
```

その後、まとめた後のcommitに設定するメッセージを編集するエディタが表示されるので、　メッセージを入力し、保存する。

## squashオプション

特殊なmerge。このオプションを指定してmergeするとそのブランチのcommit全てをまとめたcommitが追加される。

masterブランチにて

```md
git merge --squash 取り込みたいブランチ名
```

とする。