okinawa

IT勉強メモ

Git基礎

参考サイト

Udemy教材。わかりやすくて良かった。
Gitの仕組みも理解できた。
www.udemy.com

Gitコマンド一覧

Gitコマンド虎の巻

用語

ワークツリー

ソースが置いてある、ローカルの作業ディレクトリ。ワークスペース。 git initした場所。

ステージングエリア

スナップショットの保存場所。

ステージングエリアはなぜ必要?
コミットの内容を選択するため。

基本的には1つのコミットに1つの目的。
例:バグ修正と機能追加の2つの修正を分けてステージングしてからコミットする

ローカルリポジトリ

スナップショットの保存場所。

リモートリポジトリ

複数人で共有するリポジトリ

スナップショットの保存場所。

ワークツリーからリモートリポジトリまでの流れ

ワークツリー → add →ステージングエリア → commit → ローカルリポジトリ → push → リモートリポジトリ

.gitフォルダの中にステージングエリアとローカルリポジトリが入っている。

.gitignoreとは

バージョン管理対象外のファイルやディレクトリを管理。

.gitignoreファイルに、ファイル名やディレクトリ名を記述するだけ。

ブランチ関連

trunk

trunk(木の幹)はプロジェクトのメインとなるブランチ。

メインブランチとも言う。

基本的には常にリリース可能な状態にしておく。

トピックブランチ

機能追加やバグ修正などの特定のトピックに基づいたブランチ。

マージ

マージとは2つのブランチを1つに統合すること。

リモート追跡ブランチとは?

リモートリポジトリのブランチの位置を記憶する、ローカルリポジトリのブランチのこと。

ローカルからリモートのブランチを確認するためにある。

$ git branch -a  //ローカルとリモートのブランチ参照
  add-feature
* main
  remotes/origin/HEAD -> origin/main //remotesから始まるのが追跡ブランチ
  remotes/origin/add-feature
  remotes/origin/main

・リモート追跡ブランチの実体

.git\refs\remotes\origin\HEAD ←ここにある

HEADファイルの中身を見るとmainブランチを指している↓

ref: refs/remotes/origin/main

refs/remotes/origin/mainの中身はハッシュ値

74c32143cae0adf61217ed4ba9d351f70e74ff28

リモートリポジトリ名:origin
ブランチ名:main
コミットのハッシュ値:74c32143cae0adf61217ed4ba9d351f70e74ff28

上記がリモート追跡ブランチのHEAD(ポインタ)が指し示すコミット。

上流ブランチ

ローカルブランチに対応するリモートブランチのこと。

通常はローカルとリモートのブランチ名は同じ。

git branch -vvで対応関係が見れる。

$ git branch -vv
* bug-fix 027cf1f [origin/bug-fix] add file.txt //ローカルbug-fixはorigin/bug-fix(上流ブランチ)と対応
  main    22c4913 [origin/main] add 333 conflict solve//ローカルmainはorigin/main(上流ブランチ)と対応

$ git branch -a //全ブランチ参照
* bug-fix
  main
  remotes/origin/HEAD -> origin/main
  remotes/origin/bug-fix
  remotes/origin/main

commitとbranchの仕組み(重要)

現在どのブランチのどのコミットを参照しているかは、HEADで管理している。

HEADとは?
現在のコミット or ブランチを指し示すポインタのこと。

branchとは?
ブランチ内で現在のコミットを指し示すポインタのこと。

.gitディレクトリのHEADファイルを見てポインタを理解する

ポインタはHEADファイルで管理されている。

例1.bug-fixブランチにいるときのHEADファイル

ref: refs/heads/bug-fix

HEADが示すポインタはbug-fixブランチであるとわかる↑

次にrefs/heads/bug-fixファイルを見てみよう。

e07aee2b0bdf1992ca2c94f52a759f9be734a620

↑bug-fixブランチのポインタが示す、コミットのハッシュ値が書かれている

例2.下記のコマンドを実行後にHEADファイルを見てみる

git checkout a547125 //過去のコミットに移動
a547125b295e4cb785c7e4aca08778157ac97dd9

HEADファイルにコミットのハッシュ値が直接書かれている↑

以上のことから下記がわかる。

HEADには現在のコミット値 or 現在のブランチのパスが書かれている。

パスが書かれている場合は、そのパス(refs/heads/bug-fix)に書かれているコミット値が現在のポインタ。

detached HEADとは

HEADがどのブランチも指し示していない状態。

つまり、HEADファイルにコミットのハッシュ値が書かれている状態のこと。

ブランチを指しているときは、HEADファイルにブランチのパスが書かれている。

下記コマンドでできる。

git checkout ハッシュ値 //過去のコミットに移動

$ git checkout c82d
Note: switching to 'c82d'.

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 c82dc14 333を追加

commitの親子関係

コミットの親子関係

親:1つ前のコミット
子:1つ後のコミット

子は親がどれかわかるが、親は子がどれかわからない。

なぜなら、子から親への参照値はあるが、親から子への参照値はない。子から親への一方通行。

過去の変更履歴を調べたい時

git log --stat //変更履歴を表示。変更したファイル名も表示
git log --online --graph --all //視覚的に見やすいログ表示
git checkout ハッシュ値 //過去の変更に移動
git diff ハッシュ値1(古) ハッシュ値2(新) //差分表示

$ git diff 73df c82dc
diff --git a/README.md b/README.md
index 5386dfe..fb5bed9 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,5 @@

 新機能追加

-Githubから編集111
\ No newline at end of file
+Githubから編集111
+333
\ No newline at end of file

過去の変更に移動するとワークツリーのファイルも過去のものに置き換わるので、過去時点のファイルを参照できる。

コミットの取消方法は2つ

コミットを打ち消す git revert

最新のコミットの後に、過去のコミットを追加して打ち消す。

こっちの方がよく使われる。取消しが履歴として残るのが良い。

・例
コミットA コミットB コミットC(最新)があったとする。

コミットCの後にコミットB'を追加してコミットCをなかったコトにする。

git revert HEAD //最新コミットを1つ前に戻す

コミットA コミットB コミットC コミットB'(最新)となる。

コミットを削除 git reset

//基本はhardオプションで良さそう

git reset --hard ハッシュ値 //hardはワークツリーとステージングエリアにHEADの内容をコピー

git reset --soft ハッシュ値 //softはワークツリーとステージングエリアにHEADの内容をコピーしない

内部的にはコミットを削除しているわけではなく、ポインタを移動しているだけ。

例:bug-fixブランチでgit resetした場合

refs/heads/bug-fixに書かれているハッシュ値が変更される。

通常はbranch内の最新のコミットのハッシュ値が書かれているが、それが古いコミットのハッシュ値に変わる。

移動しているだけなので、元のコミットに戻ることも可能

git reset --hard 最新コミットのハッシュ値 //元に戻す 

共同開発

集中型と分散型

SVNは集中型。
集中型はリモートリポジトリのみ。
単純だがコミットの影響が強い。

Gitは分散型。
分散型はローカルリポジトリとリモートリポジトリがある。
複雑だがコミットはローカルリポジトリにされるので、影響小さい。

共同開発の流れ

上から順に実施する。

git clone リモートリポジトリURL //リモートリポジトリコピー

token作成(必要な場合)  githubのsettings→developer settings

git checkout -b ブランチ名 //トピックブランチ作成。現在のブランチから枝分かれするブランチを作る。ブランチの作成基準は現場によりけり。

何らかの修正作業をする。

git commit -a -m "修正完了" //add commit同時コマンド

git remote //リモートリポジトリ名を確認

---ここから。push前にリモートの変更をローカルに取り込む

git fetch リモートリポジトリ名 リモートのブランチ名 //更新。リモートリポジトリの変更をローカルリポジトリに取り込む。ただし、ローカルのHEADは変わらないので、fetchだけだと変更してないように見える。ワークツリーには影響なし。

git branch -vv //リモートとローカルの対応ブランチ確認。通常はリモートとローカル同じブランチ名。上流ブランチと言う。

git merge origin(リモートリポジトリ名)/main(リモートのブランチ名) // fetchした変更を取り込む。ローカルのブランチを移動してから行うこと。取り込むブランチがmainならmainに移動後。

git pull origin(リモートリポジトリ名) main(リモートのブランチ名)//fetch + merge。普段はこっちを使う。毎日orプルリク前に実行。コンフリクト発生時は修正。

---ここまで

git push リモートリポジトリ名 ローカルのブランチ名:(省略可)リモートのブランチ名 //リモートリポジトリに反映。

コンフリクト発生したら
 コンフリクト修正
 再度 add commit pushする

git branch -a //push成功確認。リモートリポジトリのブランチの位置確認。リモート追跡ブランチ。

git log --graph --online //push成功確認2。ローカルリポジトリとリモートリポジトリのHEADの位置が同じならOK。

$ git log --graph --oneline
* 74c3214 (HEAD -> main, origin/main, origin/HEAD) edit on github //ローカルとリモートのHEAD位置が同じ
*   a884db8 Merge pull request #1 from parapore/add-feature
|\
| * 20ce4de (origin/add-feature, add-feature) fix bug add-feature
| * c2e2d51 add feature README
|/
* c2ab11f Initial commit

プルリクエスト送る
 github画面からプルリクエスト選択→ブランチ選択→create pull request→コメント書く→create pull request

プルリクエストに対して修正が入ったら?
 再度修正、add,commit&PUSH。プルリクエストは送らなくてよい。

git push --delete origin(リモートリポジトリ名) add-feature(削除するブランチ名)//不要になったトピックブランチを削除する。やらなくてよいかも?

コンフリクトが発生した場合は?(merge)

コンフリクトを解消してファイル保存。

git merge ブランチ名  //←ここでコンフリクト発生
コンフリクトを手動修正
git add ファイル名 //mergeではなくadd
git commit -m ”コンフリクトを修正”

マージというのは、別のブランチの変更をHEADブランチにadd commitしている。
そのため、再度mergeは必要なく、add commitのみでOK。

コンフリクトが発生した場合は?(pull)

$ git pull origin main //コンフリクト発生
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 688 bytes | 172.00 KiB/s, done.
From https://github.com/parapore/git-remote-dev
 * branch            main       -> FETCH_HEAD
   73dfa15..c657740  main       -> origin/main
error: Your local changes to the following files would be overwritten by merge: 
        README.md
Please commit your changes or stash them before you merge. //コミットしろと言っている
Aborting
Updating 73dfa15..c657740

$ git commit -a -m "333を追加" //コミット
[main c82dc14] 333を追加
 1 file changed, 2 insertions(+), 1 deletion(-)

$ git pull origin main //再度pullでコンフリクト内容がエディタに表示される
From https://github.com/parapore/git-remote-dev
 * branch            main       -> FETCH_HEAD
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

↓ コンフリクト内容がエディタに表示される

コンフリクト発生時のエディタ

vscode

コンフリクト解消

vscode2

コミットとプルリクエストのタイミング

コミットは切りの良いところで。
1ファイルの変更が終了したらとか、1日の終わりとか。

プルリクエストのタイミングは現場次第。
完了してからの場合もあれば、途中でプルリク送ってチェックしてもらいながらのケースも有り。

コマンド

git init

カレントディレクトリがワークツリーとして設定される。

.gitというディレクトリが作成される。

.gitディレクトリがステージングエリアやローカルリポジトリの実体。

git log

all:全てのコミット履歴を表示。本来見れない子コミット(未来分)も。

oneline:コミットメッセージとHASH値のみ

graph:コミットの枝を視覚的に表示

onelineとgraph療法指定すると見やすいログになる。

$ git log --oneline
74c3214 (HEAD -> main, origin/main, origin/HEAD) edit on github
a884db8 Merge pull request #1 from parapore/add-feature
20ce4de (origin/add-feature, add-feature) fix bug add-feature
c2e2d51 add feature README
c2ab11f Initial commit


$ git log --graph
* commit 74c32143cae0adf61217ed4ba9d351f70e74ff28 (HEAD -> main, origin/main, origin/HEAD)
| Author: parapore <53287775+parapore@users.noreply.github.com>
| Date:   Sun Jan 7 11:35:14 2024 +0900
|
|     edit on github
|
*   commit a884db8ba5078dc0134307e96cd12f450f1857ea
|\  Merge: c2ab11f 20ce4de
| | Author: parapore <53287775+parapore@users.noreply.github.com>
| | Date:   Sun Jan 7 10:54:02 2024 +0900
| |
| |     Merge pull request #1 from parapore/add-feature
| |
| |     README.mdに新機能を追加。
| |
| * commit 20ce4de3740ae2a249616403a39af55cfe9e7b65 (origin/add-feature, add-feature)
| | Author: parapore <eriglai577@gmail.com>
| | Date:   Sun Jan 7 10:45:43 2024 +0900
| |
| |     fix bug add-feature
| |
:
* commit 74c32143cae0adf61217ed4ba9d351f70e74ff28 (HEAD -> main, origin/main, origin/HEAD)
| Author: parapore <53287775+parapore@users.noreply.github.com>
| Date:   Sun Jan 7 11:35:14 2024 +0900
|
|     edit on github
|
*   commit a884db8ba5078dc0134307e96cd12f450f1857ea
|\  Merge: c2ab11f 20ce4de
| | Author: parapore <53287775+parapore@users.noreply.github.com>
| | Date:   Sun Jan 7 10:54:02 2024 +0900
| |
| |     Merge pull request #1 from parapore/add-feature
| |
| |     README.mdに新機能を追加。
| |
| * commit 20ce4de3740ae2a249616403a39af55cfe9e7b65 (origin/add-feature, add-feature)
| | Author: parapore <eriglai577@gmail.com>
| | Date:   Sun Jan 7 10:45:43 2024 +0900
| |
| |     fix bug add-feature
| |

$ git log --graph --oneline
* 74c3214 (HEAD -> main, origin/main, origin/HEAD) edit on github
*   a884db8 Merge pull request #1 from parapore/add-feature
|\
| * 20ce4de (origin/add-feature, add-feature) fix bug add-feature
| * c2e2d51 add feature README
|/
* c2ab11f Initial commit

git branch

-a:追跡ブランチ含め全て表示

-vv:詳細表示。上流ブランチも表示(ローカルブランチに対応するリモートブランチのこと)

$ git branch
* main

$ git branch -a
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/main

$ git branch -vv
* main 74c3214 [origin/main] edit on github //ローカルmainの上流ブランチはリモートmain

参照系

git ls-files //ステージングエリアを参照
git diff //ワークツリーとステージングエリアの差分
git diff --cached //スージングエリアとローカルリポジトリの差分
git diff HEAD //ワークツリーとローカルリポジトリの差分
git diff //ハッシュ値1 ハッシュ値2 //過去にコミットした履歴同士の差分
git log //コミット履歴の確認
git log --stat //統計情報の確認
git status //addやcommitされてない変更がないか?バージョン管理対象外ファイルがないか?を調べる。

その他

git add ファイル名
git commit -m "コミットメッセージ"
git rm --cached //ファイル名 ステージングエリアのファイル削除
git rm -r --cached //ディレクトリ名 ステージングエリアのディレクトリ削除
git mv 旧ファイル名 新ファイル名 //普通にファイル名を変更すると、バージョン管理対象外になってしまう。
git mv ファイル名 ディレクトリ名 //ファイルを別のディレクトリに移動
git merge ブランチ名
git checkout -b ブランチ名 //ブランチを新規作成して、新規ブランチにHEADを移動
git checkout ハッシュ値 //過去のコミット履歴に移動
git branch -d ブランチ名 //ブランチ削除。実際には削除せず、ポインタのみ削除。コミットは残る。