====== git ======
===== 概要 =====
* 分散バージョン管理ツール
===== インストール =====
==== apt からインストール ====
$ sudo apt install git
==== 最新版をインストール ====
$ sudo add-apt-repository ppa:git-core/ppa
$ sudo apt update
$ sudo apt install git
* 参考サイト: [[https://loumo.jp/archives/23149 | Ubuntu で git のバージョンを最新版にする | Lonely Mobiler]]
==== 初期設定 ====
* ユーザ名とメールアドレスを登録する\\ $ git config --global user.name "hoge"
$ git config --global user.email "hoge@example.com"
* ''--global'' はデフォルトとして設定すること意味するため、以降は設定が不要になる (ただし、リポジトリ毎に異なるユーザ名とメールアドレスを使う場合はリポジトリ毎に、''--global'' を抜いて設定する。詳しくは使い方のリポジトリの作成を参照)。
* 誤って、''--global'' を付けてしまった場合は、以下のコマンドで削除できる。\\ $ git config --global --unset user.name
$ git config --global --unset user.email
* なお、この設定は ''$HOME/.gitconfig'' にも記述されているので、エディタで ''[user]'' 項目を編集することでも対処できる。
===== 使い方 =====
==== リポジトリの作成 ====
$ mkdir REPOSITORY_NAME
$ cd REPOSITORY_NAME
$ git init
* ユーザ名とメールアドレスを設定していなかった場合は、ここで登録する。\\
$ git config --global user.name "hoge"
$ git config --global user.email "hoge@example.com"
==== ファイルのステージング ====
* 特定ファイルの追加\\ $ git add FILE
* ''FILE'': 登録したいファイル (ただし、add しただけでは登録されない) (複数指定可)
* 特定ファイルの削除\\ $ git rm FILE
* ''FILE'': 登録したいファイル (ただし、rm しただけでは登録されない) (複数指定可)
* 特定ファイルの名前変更\\ $ git mv FILE RENAMED_FILE
* ''FILE'': 名前の変更をしたいファイル
* ''RENAMED_FILE'': 変更後のファイル名
* すべてのファイルの追加・削除・名前変更\\ $ git add -A
* ファイルの変更内容から追加、削除、名前変更が自動的に推測される
* ステージングの取り消し\\ $ git reset HEAD FILE
* ''FILE'': 取り消したいファイル (複数指定可)
* ''HEAD'' は git Ver. 1.8.5 から ''@'' に置き換えても良くなった。
==== ファイルの状況確認 ====
* 状況確認\\ $ git status
* なにも表示されない: ローカル上でファイルの変更がない場合
* ''??'': ファイルがこれまで登録されておらず、ステージングもされていない
* ''A'': ファイルの追加がある (add 済み)
* ''D'': ファイルの削除がある (rm 済み)
* ''R'': ファイルの名前変更がある (mv 済み)
* ''M'': ファイルの変更がある
==== コミット ====
* コミット (実登録)\\ $ git commit
* この後に、エディタが起動し、コミットメッセージを登録する。
* メッセージ付きコミット\\ $ git commit -m 'MESSAGE'
* ''MESSAGE'': コミットメッセージ
* コミットメッセージをファイルから読み込む場合\\ $ git commit --file FILE
* ''FILE'': コミットメッセージを読み込むファイルのパス
* コミットの上書き\\ $ git commit --amend
* コミット直後であれば、再編集して上記コマンドで再登録可能
==== コミットの履歴表示 ====
* デフォルト\\ $ git log
* コミットのハッシュ値 (COMMIT)、コミット実行者、コミット日時が履歴順に表示される。
* log のオプション
* ''--oneline'': 履歴を 1 行 1 コミットで表示
* ''--graph'': アスキーグラフで表示
* ''--p'': 差分を表示
* ''--stat'': 変更された行数を表示
* ''-2'' 直近の 2 コミットを表示 (数字は変更可)
* ''--decorate'': 現在の HEAD、ブランチ名、タグ名を表示
==== コミットについて ====
* 現在のコミットは ''HEAD'', ''@'' (Ver. 1.8.5 から), コミットのハッシュ値で表現できる。
* 前のコミットは、''HEAD'' の後に ''^'' や ''~''、''^{n}'', ''~n'' を付けるか、コミットのハッシュ値で表現できる
* 例
* ''HEAD^'', ''@^'', ''HEAD^{1}'', ''HEAD~1'', ''@^{1}'', ''@~1'': 一つ前のコミット
* ''HEAD^^^'', ''@^^^'', ''HEAD^{3}'', ''HEAD~3'', ''@^{3}'', ''@~3'': 3 つ前のコミット
* ここでは、コミットを ''COMMIT'' で表現する
==== コミットの削除 ====
* 直前のコミット削除\\ $ git reset --hard HEAD^
* ''--hard'': 作業ディレクトリの内容も 1 つ前の状態に戻す (コミット内容と同じにする)
* ''--soft'': ''--hard'' の代わりに与えるオプションで、作業ディレクトリの内容は維持する
* ''HEAD^'': 直前のコミットを示す
* 直前のコミット削除 (マージコミットの完全削除)\\ $ git reset --hard ORIG_HEAD
* push 後には使えない。
* push 後の削除は、revert コマンドを使って、前の状態に戻した履歴を残す必要がある。\\ $ git revert -m 1 MERGE_COMMIT
* ''-m'' で残す親を指定する。
* 参考サイト: [[https://qiita.com/chihiro/items/5dd671aa6f1c332986a7 | 【git】マージしたけどやっぱりやめたい時のやり方4種類 - Qiita]]
* 指定コミット以降の削除\\ $ reset --hard COMMIT
* ''COMMIT'' 以降に登録されたコミットが削除される
* 直前のコミットは消さずに以前のコミットを呼び出す\\ $ git revert COMMIT
* 既に push 済みのものは編集できないため、過去のコミットを改めて呼び出し、改めてコミットするという流れになる時に使う。
* 過去のコミット以降を編集・削除する
- 特定の過去のコミットを指定する (編集できるのはそれ以降のコミット)。\\ $ git rebase -i COMMIT
- エディタが起動し、操作とコミットが表示されるので、操作を編集する。
* 操作の表記
* ''pick'': このまま維持
* ''reward'':
* ''edit'': 編集
* ''squash'': 直前のコミットに統合
* ''fixup'': ''squash'' に加え、ログ自体からも破棄
* ''exec'':
* ''drop'': コミットの削除 (conflict が起こった場合、conflict を解消するために何度も質問される)
==== コミット間の移動 (過去の状態に戻す) ====
* 特定のコミットに移動する場合 (ただし、ローカルに変更があった場合は、変更ファイルの状態を維持する)\\ $ git checkout COMMIT
* ローカルの変更を無視して、特定のコミットに移動する場合 (変更ファイルも特定コミット状態になる)\\ $ git checkout -f COMMIT
* 特定のファイルのみ特定のコミットに戻す\\ $ git checkout COMMIT FILE
* ''FILE'': 戻したいファイル
* 特定のファイルのみ特定のコミットに戻す (ローカルの変更無視)\\ $ git checkout -f COMMIT FILE
* ''FILE'': 戻したいファイル
* 特定のファイルの過去のバージョンを別ファイルとして取り出す
* cat-file を使う方法\\ $ git cat-file -p COMMIT:FILE1 > FILE2
* show を使う方法\\ $ git show COMMIT:FILE1 > FILE2
* ''COMMIT'': コミットのハッシュ値
* ''FILE1'': 戻したいのファイル
* ''FILE2'': 保存先
==== タグ ====
* 特定のコミットにタグを付けて、バージョン番号など任意の名前を付けることができる。
* 現在のコミットにタグの追加\\ $ git tag "TAG"
* ''TAG'': タグ名
* 現在のコミットに注釈付きタグの追加\\ $ git tag -a "TAG" -m "TEXT"
* ''TAG'': タグ名
* ''TEXT'': 注釈
* 特定のコミットにタグを付ける\\ $ git tag "TAG" COMMIT
$ git tag -a "TAG" -m "TEXT" COMMIT
* タグの一覧表示\\ $ git tag
* タグの削除\\ $ git tag -d "TAG"
* ''TAG'': タグ名
* タグの push (タグはリモートにデフォルトでは反映されない)\\ $ git push origin --tag
==== ブランチ ====
* ブランチの作成 (コミットを分岐させる時に使う; 仕様で迷った場合等)\\ $ git branch BRANCH_NAME
* ''BRANCH_NAME'': ブランチ名
* ブランチの一覧表示\\ $ git branch
* ブランチの削除 (マージ済みのブランチのみ)\\ $ git branch -d BRANCH_NAME
* ''BRANCH_NAME'': ブランチ名
* ブランチの削除 (ローカル)\\ $ git branch -D BRANCH_NAME
* ''BRANCH_NAME'': ブランチ名
* ブランチの削除 (リモート)\\ $ git push origin :BRANCH_NAME
* ''BRANCH_NAME'': ブランチ名
* ブランチの名前変更 (ローカル)\\ $git branch -m BRANCH_NAME NEW_NAME
* ''BRANCH_NAME'': 変更したいブランチ名
* ''NEW_NAME'': 変更後のブランチ名
* ブランチ間の移動\\ $ git checkout BRANCH_NAME
* ''BRANCH_NAME'': ブランチ名
* デフォルトのブランチ名は ''master''
* ブランチ間の移動 (ローカル無視)\\ $ git checkout -f BRANCH_NAME
* ''BRANCH_NAME'': ブランチ名
* デフォルトのブランチ名は ''master''
==== ブランチのマージ ====
* ブランチのマージ (fast-forward)\\
$ git checkout MERGED_BRANCH
$ git merge MERGE_BRANCH
* ''MERGED_BRANCH'': マージ先ブランチ (たいていは master)
* ''MERGE_BRANCH'': マージするブランチ
* デフォルトで ''--ff'' オプションが適用されており、fast-foward のマージになる。
* fast-forward: 取り込み先ブランチにコミットがないマージに HEAD のみを変更するマージ方式 (ただし、開発ブランチ、マスターブランチを分けている場合に、どこからどこまでが開発ブランチかという境界がわかりづらくなる)
* fast-forward でない例:\\
,-D-E-F.
-A-B-C--------`G-
* D-E-F が G へとマージされるが、D-E-F が別ブランチである情報を残っている
* mercurial はデフォルトでこっちの挙動になる。
* fast-forward のマージ後の例:\\ -A-B-C-D-E-F-
* D-E-F がマージされ一本化する
* HEAD が移動するだけなので、G が作られない
* ブランチのマージ (no-fast-forward)\\
$ git checkout MERGED_BRANCH
$ git merge --no-ff MERGE_BRANCH
* ''MERGED_BRANCH'': マージ先ブランチ (たいていは master)
* ''MERGE_BRANCH'': マージするブランチ
==== コミット日時の変更 ====
* 過去に管理していなかったファイルをコミットする際に、開発日時にしたい場合がある。
* その場合にコミット日時を変更する必要があるが、git には、実際のコミット日時と author_date が設定されており、ここでは author_date を変更する方法を紹介する (git log で表示されるのは author_date の方)。
* コミット直後に日時を変更する例: \\ $ git commit --amend --date='Fri Aug 28 00:00:00 2019 +0900'
* ''Fri'': 曜日を金曜日に設定する (合ってないとこの項目は無視される)
* ''Aug'': 8 月に設定する
* ''28'': 28 日 (8月の) に設定する
* ''00:00:00'': 00:00:00 に設定する
* ''2019'': 2019 年に設定する。
* ''+0900'': タイムゾーンを +0900 に設定する
* 過去のコミットの日時を変更する場合
- 修正したいコミットの直前のコミットを指定する\\ $ git rebase -i COMMIT
- エディタが起動するので、コミット日時を変更したいコミットの左側を ''pick'' から ''edit'' にする
- コミット直後に日時を変更する例のように ''commit --amend'' で日時を指定する
- 日時を反映させる\\ $ git rebase --continue
==== git のリモート先の変更 ====
- 現在のリポジトリに適用されているリモートの URL を確認する。\\ $ git remote -v
- 移行先の新しい URL を設定する。\\ $ git remote set-url origin NEW_URL
* ''NEW_URL'' 移行先の URL
* 参考サイト: [[https://qiita.com/minoringo/items/917e325892733e0d606e | gitのremote urlを変更する(レポジトリ移行時) - Qiita]]