どうもこんにちは!
サバ缶(@tech_begin)です。
個人、業務関わらず、Gitは多くの場面で利用されています。
しかし、SourcetreeやGitKrakenなどの「Gitクライアント」を使用していると、唐突に起きた問題に対処できないことがあります。
抽象化・簡略化されているものは便利ないっぽう、本質を理解しないまま素通りしてしまいかねません。
今回はそんな自戒も含めて、Gitコマンドを学習しました。そのまとめです。
今回参考にした書籍は以下のものです。
- Gitリポジトリの作成
- 差分のステージング
- 差分のコミット
- ブランチの確認
- ブランチ名の変更
- リモートリポジトリと紐付ける
- プッシュする
- 上流ブランチを登録する
- クローンする
- ブランチを確認する
- ブランチを作成する
- ブランチを削除する
- ブランチを切り替える
- マージ
- リポジトリの状態確認
- ファイル差分の状態確認
- コミットログの確認
- 一連の流れ
- コンフリクト解消
- リモートブランチの確認
- ブランチの削除
- ブランチ名の変更
- リモートリポジトリの情報をローカルに持ってくる
- 特定のコミットを取り入れる
- 操作を取り消す
- コミットを修正する
- コミットログを確認する
- 差分
- コミットの中身を確認する
- 作業履歴を確認する
- ファイルとディレクトリを削除する
- ファイル名とディレクトリ名を変更する
- ファイルの編集履歴を確認する
- 空のディレクトリをGitで管理する
- リベースで変更を取り込む
- 参考文献
- 全体の流れをざっくり
Gitリポジトリの作成
git init
このコマンドを任意のディレクトリ内で実行すると、.git
ファイルが追加されます。ls -la
コマンドで確認してください。
差分のステージング
ワーキングツリー(実際に作業しているディレクトリ)から、インデックスエリア(Gitのリポジトリとの間)に登録する際『ステージング』という操作を行います。
この『インデックスエリア』を単純に『インデックス』や『ステージングエリア』とも呼ばれているようです。呼び方についてはまちまち。
このステージングは、add
を実行することで可能です。
git add practice2.txt
git add . #カレントディレクトリ全体をステージングすることも可能
差分のコミット
インデックスエリアに登録されたものが、コミット対象となります。
コミットすることで、ローカルリポジトリに差分を登録することができます。セーブ地点みたいなものです。
git commit -m "[fix] practice3.txt" # コメント付きコミット
git commit # エディタが開く。そこでコメントを書き、:wqでコミットされる
ブランチの確認
現時点で手元のディレクトリに存在するブランチを確認します。
$ git branch
* master # アスタリスクがついているのがカレントブランチ(現在のブランチ)
ブランチ名の変更
ブランチを変更したいときは、以下のように「-m」オプションをつけます。
変更したいブランチを選択(チェックアウト)しておきましょう。
$ git branch -m main #ブランチ名変更
$ git branch
* main # masterだったのが、mainに変わってる!
リモートリポジトリと紐付ける
以下の2点を事前に行なってください。
- GitHubにリポジトリを作成していること
- SSH鍵の登録が完了していること
今回の例では、GitHubと紐付けます。
git remote add origin git@github.com:yamada/git-practice-80.git
error: remote origin already exists.
というエラーが出力された場合は以下の記事を参照してください。
リモートリポジトリとの紐付けを確認します。
vi .git/
以下の画像のような表示になります。
矢印キーを使って「config」を選択し、エンターキーで開きます。
[remote “origin”]のurlが指定のリポジトリになっていれば、連携できています。
前の状態に戻るには「esc」キーを押して、「:q」と入力してください。
プッシュする
先ほど、リモートリポジトリとの連携を確認しました。
それでは次に、ローカルリポジトリにコミットした内容を、リモートリポジトリへ反映させていきます。
この操作を『プッシュ』と言います。
git push origin main
上流ブランチを登録する
毎回ブランチ名を記述するのは面倒。
そんな時に便利なのが、 -u
オプション。
これを使うことで、自動的にリモートブランチの引数を設定してくれます。
-u
は、--set-upstream
オプションの略称で、upstream(上流)という意味があります。
次回以降からは git push
のみでOKになります。
git push -u origin main # 上流ブランチを登録できる。
クローンする
途中でプロジェクトに参画した場合、大抵はリモートリポジトリをローカル環境にダウンロードしてから作業を開始します。
この操作を『クローン』と呼びます。
すでにあるリモートリポジトリを、ローカル環境へダウンロードする作業が「クローン」です。
git clone git@github.com:yamada/git-practice-80.git
今回は新規で作成したリポジトリをいじってやってるので、実施しません。
試したい場合は、すでにあるリポジトリを使ってみましょう。
以下のようなGithubで公開されているリポジトリでお試しください(以下は一例です)。
ブランチを確認する
既出ですが、ここで今一度ブランチを確認してみましょう。
git branch
ブランチを作成する
ブランチを作成したい際は、非常に単純なコマンドで可能です。
以下は、developブランチを作成する例です。
git branch develop
ブランチを削除する
ブランチ名を間違えた場合は、削除できます。
git branch -d develo # 間違えてdeveloとしていた場合。
名前を変更することでも対処可能です。
注意点として、カレントブランチ(現在選択しているブランチ)に対してブランチ削除コマンドは実行できません。
ブランチを切り替える
カレントブランチを切り替えます。
以下は、developブランチに切り替えるコマンドです。
git switch develop
git switch -c feature # ブランチ作成とチェックアウト(カレントブランチに切り替えること)を同時に実行する
マージ
リリース前にはブランチを全てマージ(合流、合併)させる必要があります。
例えば、main
ブランチを本流としたリポジトリがあり、そこに対して不具合修正をしたブランチを合流させるというイメージです。
以下では、developブランチで作業をした後、mainブランチにdevelopブランチをマージする流れを示します。
まず、developブランチにした状態で、テキストを作成した差分をコミットします。
git switch develop
touch practice9.txt
git add practice9.txt
git commit -m "practice9.txt"
ls # practice9.txtはある
次にmainブランチへ切り替えます。先ほどのコミットはdevelopブランチにしかないため、追加したテキストファイルは存在しません。
git switch main
ls # practice9.txtはない
ここでマージ作業をします。
「main ← develop」というイメージです。
git merge develop
ls # practice9.txtがある!
マージされていることを確認する
現在作業中のブランチに、どのブランチがマージされているかを確認します。
上記の続きでやると、「mainブランチに何のブランチがマージされているか」を確認できますね。
ちなみに現状、「develop」のみが表示されるはずです。
git branch --merged
マージされていないブランチを確認する
逆にマージされていないブランチを確認することも可能です。
マージされていないブランチがない場合は、何も表示されません。
git branch --no-merged
リポジトリの状態確認
試しにテキストファイルを新規作成し、その直後に状態を確認してみます。
touch practice10.txt
git status
On branch main
Untracked files:
(use "git add …" to include in what will be committed)
practice10.txt
nothing added to commit but untracked files present (use "git add" to track)
最後に、「未追跡ファイルがある」と言っていますね。
ファイル差分の状態確認
ここからは流れに沿って進めていきます。
①追跡されていないファイルの[状態]確認
$ touch practice11.txt
$ git status
On branch main
Untracked files:
(use "git add …" to include in what will be committed)
practice11.txt
nothing added to commit but untracked files present (use "git add" to track)
コミットされていないため、追跡対象となっていません。
なので、Untracked(未追跡)になっています。
②追跡されていないファイルの[差分]確認
①の続きです。
$ git diff # 何も表示されない
③追跡されているファイルの[状態]確認
②の続きになります。
$ git add practice11.txt
$ git status
On branch main
Changes to be committed:
(use "git restore --staged …" to unstage)
new file: practice11.txt
新規追加したファイルをaddした状態では、Changes to be committed(コミットすべき変更があるよ)と出るだけです。
コミットします。
$ git commit -m "practice11"
[main 7a94ba2] practice11
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 practice11.txt
$ git status
On branch main
nothing to commit, working tree clean
ワーキングツリーは綺麗ですよ(コミットすべきものはないです)と表示されました。
差分が出るように、practice11.txtをいじります。
追跡しているファイルの状態を確認します。
$ echo "change practice11" >> practice11.txt # ファイルにテキスト追記
On branch main
Changes not staged for commit:
(use "git add …" to update what will be committed)
(use "git restore …" to discard changes in working directory)
modified: practice11.txt
no changes added to commit (use "git add" and/or "git commit -a")
④追跡されているファイルの[差分]確認
$ git diff
diff --git a/practice11.txt b/practice11.txt
index e69de29..40b4deb 100644
--- a/practice11.txt
+++ b/practice11.txt
@@ -0,0 +1 @@
+change practice11
ワーキングツリー(addしてない部分)とインデックス(コミットしてない部分)との差分が表示されています。
⑤ステージングされているファイルの[状態]確認
③の最初のやつと同じ感じです。
Change to be committedが表示されてるところ。
On branch main
Changes not staged for commit:
(use "git add …" to update what will be committed)
(use "git restore …" to discard changes in working directory)
modified: practice11.txt
no changes added to commit (use "git add" and/or "git commit -a")
⑥ステージングされているファイルの[差分]確認
$ git diff --cached # git diffなら表示される
ステージングされているファイル(インデックス)と、ローカルリポジトリの差分を確認するコマンドです。
なので、⑤の時点でgit diffを実行しても何も表示されません。
$ git add practice11.txt # ステージングする
$ git diff # 表示されなくなる
$ git diff --cached # 表示される(一つレイヤが上に行ったイメージ)
コミットログの確認
$ git log
$ git log --oneline # 省略形で表示される
一連の流れ
差分が生じる(echo “change practice13” >> practice13.txt)
git diff 差分を確認 ワーキングツリー⇆ステージングエリアの差分を確認
git status リポジトリの状態を確認
git add practice13.txt ファイルをステージング
git diff --cached ステージングエリア⇆ローカルリポジトリの差分を確認
git commit -m "practice13-2" コミット
git push
もし、以下のようなエラーが表示されたら、
fatal: The current branch main has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin main
書いてある通り、 git push -u origin main
を実行しましょう。
まだ上流ブランチが登録されていないだけのようですね。
コンフリクト解消
【例】mainブランチ、developブランチでそれぞれpractice14.txtというファイルを追加して、add→commitしていた場合。
この時は、どちらのブランチも空ファイルなので差分はない=コンフリは起きない
⏬
では、コンフリを起こすためにmainとdevelopで同じファイル(practice14.txt)の同じ行を編集してコミットします。(switch, touchなどを使用して準備しよう)
⏬
mainブランチの状態で、developブランチをマージします。
$ git merge develop
CONFLICT (add/add): Merge conflict in practice14.txt
Auto-merging practice14.txt
Automatic merge failed; fix conflicts and then commit the result.
コンフリクトが起きました。
コンフリクトを確認
コンフリクトが起きたファイルの中身を確認します。
$ cat practice14.txt
を実行します。ファイル名は適宜変えてくださいね。
<<<<<<< HEAD
main branch
=======
develop branch
>>>>>>> develop
=======を挟んで、上部のHEADの部分が現在いるブランチ(ここではmainブランチ)、下部の部分がマージしようとしているブランチ(ここではdevelopブランチ)です。
コンフリクトを解消
単純に、エディタで修正し、保存するだけです。
どちらを優先するか自身で判断して編集してください。
そして、add→commitするだけでコンフリクト解消は完了です。
(マージした時にコンフリが起きているので、再度マージする必要はない。解消させるだけでOK)
※cherry-pick, rebase, pullといったコマンド実行時にもコンフリクトは起きがち。
リモートブランチの確認
git branch -r
ブランチの削除
マージされているブランチの削除
git branch -d develop
マージされていないブランチの削除
git branch -D develop
事故防止のため、意図的に未マージのブランチを削除する際に-D
オプションを使います。
ブランチ名の変更
$ git branch -m develop develop2
$ git branch -m develop2 #第一引数は省略可能
リモートリポジトリの情報をローカルに持ってくる
$ git fetch origin main
$ git fetch
特定のコミットを取り入れる
$ git cherry-pick
操作を取り消す
追跡されているファイルでステージングされていない(ワーキングツリー)ものの変更を取り消す場合
$ git restore practice22.txt
$ git restore . #カレントディレクトリ全体に適用することも可能
ステージングした変更を取り消す
$ git reset HEAD # 引数のHEADは直前のコミットを指している。
HEADとは、現在のブランチを参照しており、ブランチの最新コミットのことを言います。
$ git reset
でもOKです。
ファイル名を指定してステージング前にもどす
$ git reset -- practice24.txt
コミットをインデックスエリアまで戻す
$ git reset --soft HEAD^
コミットしてしまったものを戻すためには、–softオプションを使用する。
引数のHEAD^で、HEADをHEAD(最新コミット)のいくつ前に戻すかを選択する。
「^(カレット)」は、いくつ前のコミットに戻すかを示す。
^が1つだと1つ前のコミットを表す。
resetコマンドの3つのオプション
- git reset –soft
- HEADのみに変更を加える
- git reset –mixed
- HEAD, Indexを元に戻す(HEADとインデックスを、指定したコミットに戻している)
- git reset –hard HEAD^
- HEAD, Index, Working treeを元にもどす
コミットを修正する
直前のコミットメッセージを修正するには、–amend(改めるという意味がある)オプションを利用する。
git commit --amend -m "practice23"
コミットログを確認する
$ git log --graph
$ git log --graph --oneline
$ git log --graph --all --oneline
$ git log --prettry
(END)と表示されたら、”q”を押下します。
差分
ブランチ間のファイル差分を確認する
$ git diff main develp practice28.txt
$ git diff main..develop practice28.txt # 上と同じ
ブランチ間の差分を確認する
$ git diff main develop
コミットの中身を確認する
git show
git show --oneline
git show <コミット>
git show <コミット>:<ファイル名> # git show 1ae6c65:practice29.txt
作業履歴を確認する
ブランチの変更やマージなどの作業履歴を確認します。
git reflog
git reflog -<作業履歴数> # git reflog -2
git switch
のようなブランチ切り替えも、履歴として残ります。
ファイルとディレクトリを削除する
追跡中のファイルが不要になり、削除したいケースです。
①ファイルを削除し、add→commit
rm→add→commit
②Gitコマンドを使用し、ファイルを削除・ステージング
git rm practice31-2.txt # ファイルを削除し、削除したことをステージングできる
③Gitコマンドを使用し、ディレクトリごと削除・ステージング
git rm -r data
ファイル名とディレクトリ名を変更する
①普通にやる
mv practice32-1.txt renamed-practice32-1.txt
②Gitコマンドを使用し、ファイル名を変更してステージング
git mv practice32-1.txt renamed-practice32-1.txt
③Gitコマンドを使用し、ディレクトリ名を変更してステージング
git mv data data2
ファイルの編集履歴を確認する
git blame
git blame -s practice37.txt # -sオプションは、編集者と作成のタイムスタンプを省略する意味のSuppressの略称
空のディレクトリをGitで管理する
Gitでは、ファイルを追跡するため、空のディレクトリが作成されたことを認識することができません。
そのため、git statusで見てみても、Untracked filesと出力されます。
空のディレクトリを管理する場合には、空のファイルを作成して対処します。
慣習的に「.keep」「.gitkeep」などと命名することが多いです。
touch data/.gitkeep
リベースで変更を取り込む
git rebase main
参考文献
全体の流れをざっくり
以下に、リポジトリ作成からの流れを記述します。メモ程度に捉えてください🙇♂️
$ mkdir git-practice-80 #ディレクトリ作成
$ cd git-practice-80 #そのディレクトリに入る
$ ls -la #中身が空っぽであることを確認
$ git init
$ ls -la #「.git」が追加されていることを確認
$ touch practice2.txt #テキストファイルを作成
$ git add practice2.txt #Addする(git add . #カレントディレクトリをaddすることも可能)
$ touch practice3.txt #テキストファイルをさらに作成
$ git add practice3.txt #Addする
$ git commit -m "practice3" #Commitする(git commit でエディタが開く。そこでコメントを書いて:wqでコミットされる)
$ git branch #ブランチを確認
* master
$ git branch -m main #ブランチ名を変更
$ git branch #ブランチを確認
* main
$ git remote add origin git@GitHub.com:yamada_taro/practice-80.git #リモートリポジトリの登録(SSHでの場合)
# 参考 -> https://qiita.com/shizuma/items/2b2f873a0034839e47ce
$ git branch #ブランチを確認
$ git branch develo #間違った名前でブランチ切っちゃった
$ git branch #ブランチを確認
* main
develo
$ git branch -d develo #指定のブランチを削除
$ git branch
$ git branch develop
$ git branch
* main
develop
$ git switch develop #ブランチ切り替え
$ git switch -c feature #めんどいので、ブランチ作成とチェックアウトを同時に実行する
#マージ
git switch develop
touch practice9.txt
git add practice9.txt
git commit -m "practice9"
ls #practice9.txtはある
git switch main
ls #practice9.txtはない
git merge develop
ls #practice9.txtがある!
# Addしていない状態で、ステータスを確認してみる
touch practice10.txt
git status
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
practice10.txt
nothing added to commit but untracked files present (use "git add" to track)
#未追跡ファイルがあると言われる。