Git初心者が本当に知りたいのはgitコマンドの前と後?
Gitを使い始めたばかりの初心者がつまずくのは、「コマンドが分からない」のではなく、「コマンドを使った結果問題が起きないかわからない」ことなのではないか、という自身の体験と体感を元に、gitコマンドの前と後で何がどう変わるのかを備忘録として残そうと思います。
ちなみに「問題が起きても戻せるでしょ。」というご意見もごもっともなのですが、そんな高度?な技を初心者に求めても、増々初心者にとっての理解のハードルが上がるだけだと思いますので、まずは問題が起きないことを前提とした一連の使い方を記載していきます。
(なぜなら私もいまだに初心者の域を出ないから。。。)
0.本記事の前提
本記事を書くにあたっての大まかな前提は以下の通り。
・システムや技術としての「Git」は「G」を大文字で記載、コマンドとしての「git」は「g」を小文字で記載
・リポジトリのモデルはGitHub Flowを採用
・大元となるブランチの名称は「master」ではなく「main」を使用
(BLMの影響を考慮し、今後は「master」という名称は使われなくなると思われるため)
・Source TreeなどのGitクライアントツールは使用せずにコマンドを使用
・git configは設定済み、git initではなくgit cloneから開始
あくまで実体験ですが、初めてGitを使うとき、全く何もない状態から始めることは少なくて、むしろ既にあるリポジトリを使うことが多いのではないかと思います。
そしてだからこそ、自分の行動が既存のリポジトリや他の人の作業に悪影響を与えてしまわないかがとても不安になります。(私は)
そのため、本記事の中では、開発が進んでいるリポジトリが既にあるという前提で記載をしていきます。
また、既に使用していますが、「リポジトリ」や「ブランチ」などの各単語の意味についてはあえて言及しません。「各単語の意味は理解したものの、実際に何がどう変わるのか」が初心者にとってつまずくポイントだと考えているからです。
1.まずは自分の作業環境を整える
前提にも記載しましたが、まず最初は下記の図のような状態からスタートすることになるかと思います。
「main」、「topicA」はブランチ名を表しています。
また、●はコミットを表しています。
上記の状態から、自分の作業環境 = ローカルリポジトリを作成します。
ローカルリポジトリを作成するには、以下のコマンドを入力します。
$ git clone リモートリポジトリのclone用URL
コマンドの実行結果は以下のようになります。
リモートリポジトリと同じブランチ構成やコミットの履歴がローカルリポジトリとして作成されます。
ちなみにローカルリポジトリの赤字で記載されている「main」ブランチは、現在の作業ブランチを表しています。
次に作業用のブランチを作成していきます。mainブランチでそのまま作業を継続するのは、どこの開発現場でも大体NGです。大抵はその作業のためのトピックブランチというものを作成し、そのブランチで作業を進めます。
新規のトピックブランチを作成する場合は、以下のコマンドを入力します。
# ブランチを作成してからチェックアウト
$ git branch topicB
$ git checkout topicB
# または、
# ブランチ作成とチェックアウトを一気に行う
$ git checkout -b topicB
コマンドの実行結果は以下のようになります。
新たにtopicBブランチが作成されます。
ちなみに私はここでtopicBブランチのところに●ができると長い間勘違いしていたのですが、この時点ではtopicBに対してコミットを行っていないため、topicBはmainブランチと同じコミットを参照しています。イメージ的には以下のような感じです。
ここまでくると、自分の作業環境の完成です。
新たにtopicBブランチが作成され、作業ブランチもtopicBに切り替わっています。そのため、このままコードの修正作業を行ったとしても、変更したらまずそうなmainブランチにも影響はありません。
2.自分の開発作業を行う
では自分の開発作業を行っていきましょう。ローカルリポジトリのtopicBブランチがチェックアウトされている状態なので、このまま開発作業を続けていくことが可能です。そして必要な修正が完了したら、それをGitに記録してもらいましょう。
自分のチェックアウトしているブランチに対して修正内容を反映する場合、修正内容をコミットするなどと言いますが、そのためにはいくつかの手順が必要です。
Gitでは、それぞれのブランチに対して修正作業をする場合、インデックスとワークツリーという考え方があります。インデックスは、ブランチにコミットする内容を登録しておくためのリストのようなものだと理解してください。そしてワークツリーは、実際に修正するファイルが格納されている自身の作業環境内のディレクトリそのものだと理解してください。
そのため、作業ブランチに対して修正内容を反映するためには、
①ワークツリーでファイルを修正
②修正内容をインデックスに登録
③インデックスから作業ブランチに対してコミット
という3つの手順で、ローカルリポジトリ上の作業ブランチに対して修正内容を反映していきます。
①の作業については単純に修正したいファイルを修正するというものなので、詳細については割愛します。
①の作業が完了したら、②の作業を行います。以下のようなコマンドを入力することで、修正作業を行ったファイルをインデックスに登録します。
# ファイル名に指定したファイルをインデックスに登録する
$ git add ファイル名
# カレントディレクトリ以下の変更があった全てのファイルをインデックスに登録する
# 変更、削除、gitでバージョン管理されていないファイルの追加も対象
$ git add .
# 変更があった全てのファイルをインデックスに登録する
# 変更、削除、gitでバージョン管理されていないファイルの追加も対象
$ git add --all
# gitでバージョン管理されているファイルの変更、削除をインデックスに登録する
# gitでバージョン管理されていない新規ファイルの追加は登録しない
$ git add --update
後から追加で修正したファイルを追加でインデックスに登録することも可能です。また、インデックスに登録した修正内容を取り消すことも可能ですが、この場での説明は割愛します。
①と②の作業が全て完了したら、③の作業に移ります。作業ブランチに対して修正内容を反映するためには、以下のコマンドを実行します。
# インデックスに登録された修正内容を作業ブランチに反映する
$ git commit -m "コミットコメント"
このコマンドを入力することで、ブランチは下記の様になります。
ローカルリポジトリのtopicBブランチが更新されましたので、ここでtopicBにコミットの●が付きます。
この後、上記の①②③を繰り返し、必要な修正作業を完了させていきます。
複数回のコミットを行ったことで、ブランチのイメージ図は以下のような状態になっているかと思います。
3.リモートリポジトリに変更内容を反映する
ここまでで、自分の修正作業を、自分のローカルリポジトリに対して反映するところまで完了しました。最終的にはプロダクトのソースコードを修正する必要がありますので、今度はリモートリポジトリに修正内容を反映させていきます。ローカルリポジトリの修正内容をリモートリポジトリに反映させるためには、以下のコマンドを入力します。
$ git push origin topicB
ブランチの状態は以下のイメージ図のような状態になります。
これでリモートリポジトリにもtopicBブランチが作成されます。
しかし、ここまでではまだリモートリポジトリに別のブランチが作成されただけで、本番環境のソースである「main」ブランチには修正内容が反映されていません。
4.mainブランチに修正内容を反映する
mainブランチに修正内容を反映させるためにはいくつか方法がありますが、まずはGitHubを利用している場合を前提に説明を記載します。
GitHubを利用している場合、Webブラウザで修正対象のリポジトリを開き、「Pull Requests」タブを開くと、「New pull request」ボタンがありますので、そのボタンを押下します。
すると、どこのブランチに対してどこのブランチから修正内容を反映させるかを選択できますので、「main」ブランチに対して、「topicB」ブランチから変更を反映させるようにブランチを選択します。
最後に「Create pull request」ボタンを押下することで、mainブランチに対しての修正内容の反映準備が完了します。
反映準備と書いたのは、GitHubのPull Requestは、誰かが修正内容をレビューして、問題ないと判断され、「Merge pull request」されることで、修正内容が反映されます。そのため、Pull Requestを出しただけではまだ修正内容が反映されていません。
Pull Requestのレビューやコメントなどの文化、あるいは業務フローや、GitHub自体の使い方まで細かいところをあげると切りがないので今回は割愛しますが、Pull Requestが承認され、mainブランチに修正内容がマージされると、ブランチの状態は以下のイメージ図のような状態になります。
5.修正作業を進めていくために
最後に、リモートリポジトリの内容が変更されましたので、その変更内容をローカルリポジトリに対して反映させます。以下のコマンドを入力します。
$ git pull
リポジトリ、ブランチの状態は、以下のイメージ図のような状態になります。
これでリモートリポジトリの内容とローカルリポジトリの内容が同期されましたので、またローカルリポジトリで作業を進めていくことができます。
尚、git pullコマンド自体にも、目的に応じて多くのオプションが用意されていますが、やはり高度な話なのでこの場での説明は割愛します。
Ex)GitHubを使わず、コマンドだけで作業する場合
私自身はGitHubを使用していますが、仮にそういったサービスを使用していない場合は、4、5の手順は以下の様に置き換えられるかと思います。
まずは以下の状態からスタートします。
次に、topicBの内容をリモートリポジトリに反映させておきましょう。
$ git push origin topicB
リポジトリは以下の状態になります。
GitHubを使わずに、コマンドだけで作業をする場合は、ローカルリポジトリでマージ作業を行います。まずは作業ブランチの切り替えを行います。
$ git checkout main
リポジトリの状態は変更されませんが、作業ブランチが切り替わります。
次に、mainブランチに対してtopicBの内容を反映させます。
以下のコマンドを入力します。
$ git merge topicB
ローカルリポジトリ上でmainブランチに修正内容が反映されます。
そして最後にローカルリポジトリの内容をリモートリポジトリに反映させるために、以下のコマンドを入力します。
$ git push origin main
リモートリポジトリは以下の状態になります。
Gitを使用したソースコードの管理フローは以上となります。
最後に
私自身はまだまだGitに対しての理解も浅く、高度な使い方やオプションを駆使することができませんので、「それは違うでしょ」、「こうすべきだ」と言ったご意見がございましたら、コメント頂けますと幸いです。
私自身の備忘録が、たった一人でも世の中の悩めるエンジニアの助けになれば幸いです。