Git

01Gitとは

Gitは、VCS(Version Control System、バージョン管理システム)の1つです。

ファイルのバージョンを効果的に管理することができ、自由に変更や更新を行ったり、過去の状態にファイルを戻したりすることが可能です。

バージョン管理システムが導入された背景には様々な要因がありますが、その中でも主要な理由の1つは「開発チーム全員が同じコードを参照しながら効率的に開発を進めること」です。特に、Gitはサーバ(リモート環境)だけでなく、個々の開発者のコンピュータ(ローカル環境)でもバージョン管理を行えるため、今日では最も広く利用されているバージョン管理システムの一つと言えます。

Gitの操作は難しくありませんが、各コマンドの動作を正しく理解しないと、プロジェクトに重大な影響を及ぼす可能性があることに注意が必要です。

環境構築

02練習用ディレクトリとリポジトリの作成

次の章では、実際にGitコマンドを実行しながら学習を進めていきます。
そのために、まずはCloud9に練習用のディレクトリを作成しましょう。
新たに、Lesson6_Gitフォルダを作成し、その中にgit-testというディレクトリを新規作成してください。

以下コマンドを実行してください。
※必ず~/environmentになっていることを確認してください。

cd Lesson6_Git/git-test

上記画面のようになっていることを確認した上で以下のコマンドを実行してください。

git init

実行後、下記のように表示されると成功です。
作成したgit-testディレクトリに「.git」と書かれたサブディレクトリが追加され、バージョン管理が可能となります。

実行後、下記のように表示されると成功です。
最後に、git-testディレクトリにファイルを1つ追加しておきます。

以下コマンドを実行してください。

// 文字列の書かれたファイルを追加(echo 文字列 > ファイル名) echo "Git test string" > file01

実行後、git-testディレクトリの中に「file01」というファイルができていたら、成功です。

基本的なGitコマンド

ここからは、作成した「git-test」ディレクトリを活用して、基本的なGitコマンドを紹介していきます。

現在の「git-test」ディレクトリの状態は、以下の図のようになります。(※重要

「git-test」ディレクトリ内のファイルたちが存在する領域を「ワーキングツリー」と呼びます。

そして、変更を反映したい内容を「ステージングエリア」→「ローカルリポジトリ」の順に移動させていきます。

「ステージングエリア」が存在する理由について疑問に思われるかもしれませんが、実はこれが非常に重要です。なぜなら、「ローカルリポジトリ」に変更を一度反映してしまうと、その変更は取り消すことが難しくなるからです。しかし、「ステージングエリア」があることで、変更を直接「ローカルリポジトリ」に反映させる前に、どのファイルを反映させるかを選択することができるのです。この段階で変更を確認し、選択することで、意図せぬ変更が「ローカルリポジトリ」に保存されることを防ぐことができます。

03add

ワーキングツリーの状態を、ステージングエリアに反映するためのコマンドです。

// 「file01」をステージする
git add file01

commit

ステージングエリアにのせた変更を、ローカルリポジトリに反映するためのコマンドです。

// ”first commit”というメッセージを付けてコミット
git commit -m "first commit"

※create mode=新しいファイルがローカルリポジトリに作られたよ!
※100644=通常のファイルだよ!(ファイルのパーミッション)

log

logを使うことで、コミットの履歴を確認することができます。先ほどのcommitを確認してみましょう。

// コミット履歴を見る
git log

※7b930913b1664bf1……=コミットを一意に識別するための値(ハッシュ値、SHA-1(シャーワン)とも呼んだりする)

commit履歴はこのような感じで確認できます。

実際にcommitする際は、「なぜそのような変更をしたのか?」というのが分かるようなコミットメッセージを残すことが大事です

それでは、次に進むために「file01」にもう一行、文字列を追加しましょう。

// 「file01」に2行目の文字列を追加
echo "Git test 2nd string" >> file01

status

ここでは現時点でのローカルリポジトリの状況を確認できます。

// 現在のローカルリポジトリの状況を表示
git status

これは「ステージングエリアに反映されていない変更あり」という状態です。

diff

変更内容を確認するには、下記のコマンドを使います。

// ワークツリーとステージングエリアの差分を確認
git diff

追加した文字列が確認できました。
2行目もステージング→コミットしておきましょう。

git add file01
git commit -m "second commit"

branch

次は、新しいブランチを作成していきます。まず、今どのようなブランチがあるのか確認しましょう。

// ブランチの一覧表示と、今いるブランチの表示
git branch

現状、「masterブランチのみ」の状態です。

checkout

今いるブランチから、新しいブランチを作成したいときは、下記コマンドを実行します。

// 「branch_a」ブランチを作成する
git checkout -b branch_a

これにより、現在は「branch_a」という名前のブランチが作成され、そのブランチは「master」と同じ状態になりました。
ブランチ間を移動したい場合、先ほどのコマンドで使用した「-b」を省略したコマンドを実行します。

// ブランチを移動する
git checkout master

master→新しいブランチ作成→masterに戻るという流れを実行できました。

ここからは、あるブランチの変更内容を別のブランチに取り込む方法について学んでいきましょう。

現在、各ブランチの状態は以下のようになっています。masterブランチとbranch_aブランチは差異がありません。

次に、branch_aブランチに移動して、ファイルに一行追加する操作を行います。

// branch_aブランチに移動(=branch_aブランチをチェックアウト)
git checkout branch_a
// 「file01」ファイルに文字列を追加
echo "Git test 3rd string" >> file01
// ステージする(これまでは"git add ファイル名"としていたが、
// git add .とすると、ワークツリーの変更点をすべてステージすることができる)
git add .
// コミット
git commit -m "commit to branch_a";

merge

次に、branch_aブランチの変更をmasterブランチに反映します。

// 変更を反映させたいブランチをチェックアウト
git checkout master
// git merge 取り込みたいブランチ名
git merge branch_a

ここまでで、「masterブランチから作成したブランチで作業を行い、変更点をmasterブランチに反映する」ということができるようになりました。

番外編:コンフリクトの解消

大規模なチームでGitを使用して開発を行う際には、必ずと言っていいほど「コンフリクト」が発生することがあります。

「コンフリクト」とは、そのままの意味で言うと「競合」のことです。つまり、異なるブランチ上で同じ行や隣接する行に対して変更が行われた場合に生じます。

コンフリクトを避けるように努力することも重要ですが、万一コンフリクトが発生した場合でも、内容を確認し、一つずつ解決していくことができます。冷静に対処すれば、問題ありません。

では、コンフリクトを発生させてみましょう。

まず、現在のファイルの中身を確認します。

cat file01

文字列が3行ある状態です。

続けて、下記のコマンドを順に実行してください。

// branch_bブランチを作成
git checkout -b branch_b
// branch_bのfile01ファイルに4行目の文字列を追加
echo "Git test 4th string" >> file01
// ステージ
git add .
// コミット
git commit -m "conflict test branch_b"

// masterブランチにもどる
git checkout master
// maseterのfile01ファイルに4行目の文字列を追加
echo "Git test 3.5th string" >> file01
// ステージ
git add .
// コミット
git commit -m "conflict test master"

実行し終えると、下記のような状態になっています。

masterブランチでも、branch_bブランチでも4行目を異なる文字列で編集しました。

この状態でbranch_bブランチをmasterブランチに取り込んでみましょう。

// branch_bをmasterに取り込む
git merge branch_b

すると、以下のように表示されると思います。

「マージできなかったぞ!file01で同じ行変更してるぞ!直してからコミットしろ!」といわれています。

それでは、修正していきましょう。

git-testディレクトリ配下のfile01を開くと、このような表示になっていると思います。

※HEAD=現在のブランチの変更内容

今回は、masterブランチでの変更とbranch_bブランチでの変更の両方を取りたいので、下のように修正して上書き保存します。

そしてコマンドプロンプトに戻り、下記のコマンドを実行していきます。

// 差分を確かめる
git diff
// ステージング
git add .
// 再マージ
git meger --continue

すると、ターミナルに確認が出てくるので、「Ctrl + X」を押して確認を閉じてください。
そうすると、以下のようになると思います。

㊗masterブランチとbranch_bブランチどちらの変更も取り入れることができました!

以上がコンフリクト解消の流れでした。

04cherry-pick

次にチェリーピックを紹介します。チェリーピックは「任意のコミットを取ってくる」というコマンドです。

それではチェリーピックを実践する準備として、下記コマンドを実行してください。

git checkout -b branch_c
echo "Git test 5th string" >> file01
git add .
git commit -m "5th string"
echo "Git test 6th string" >> file01
git add .
git commit -m "6th string"

すると、現在は下図のような状態になっています。

そしてこの状態をmasterブランチに反映させようと思いますが、

「やっぱり”Git test 6th string”はいらない!!”Git test 5th string”だけほしい!!」

というときに登場するのが、cherry-pickです。

// コミット番号が必要になるので、コミットのコメントが"5th string"の
// コミット番号をコピペしておいてください。
git log
// コミット番号をコピペしてから、masterブランチに移動
git checkout master
// 先ほど控えたコミットをmasterブランチに移動
git cherry-pick コミット番号
即座にコミットされるので、変更が反映されているか確認するために、file01ファイルを開きます。
以下のようになっていればOKです。

これで、子ブランチのある時点までの変更のみをmasterに反映することができました。

stash

別の作業が入った!別のブランチをチェックアウトしないといけないけど、今チェックアウトしているブランチの変更はまだコミットしたくない!というときに、「一時的に退避」させるためのコマンドです。

下記のコマンドを実行しながら実践してみましょう。

// branch_dブランチを作成
git checkout -b branch_d
// 文字列を追加
echo "Git test 6th string" >> file01
// statusを確認(インデックスには追加されていない状態になっているか?)
git status
// stashはスタック構造なので、saveした変更が順に積まれていく。
git stash save
// スタッシュしている変更の一覧を確認
git stash list
// この時点でのステータスを見てみると、ワークツリーに変更がないきれいな状態になっている
git status
// スタックしている一番最新の変更をワークツリーに反映する
git stash pop
// スタッシュしている変更の一覧を確認→popしたので、なくなっている!
git stash list

通常、スタッシュは複数積み上げない方が望ましいです。

ただし、複数のブランチで作業しており、複数のスタッシュが必要な場合があるかもしれません。

しかしながら、先ほど紹介した方法では最新のスタッシュしか適用することができず、最新でないスタッシュを取り出す必要がある場合もあるでしょう。そのような状況に対処するために、以下の方法を使ってスタッシュを適用する手順をご紹介します。

// 事前準備:先ほどstashでの変更をステージ→コミット
git add .
git commit -m "6th string"

// 文字列を追加→スタッシュ
echo "stash 1" >> file01
git stash save "stash 1"
// 文字列を追加→スタッシュ
echo "stash 2" >> file01
git stash save "stash 2"
// スタッシュの一覧を表示
git stash list
// 今回は"stash 1"のスタッシュを復活させます。
git stash pop stash@{適用したいスタッシュの番号}

revert

特定のコミットだけを取り消したいが、コミット履歴自体は保持したい場合、revertコマンドを使用します。

revertコマンドは、特定のコミットの変更内容を元に戻す新しいコミットを作成するためのコマンドです。

// 事前準備:先ほどのstashでの変更をステージ→コミット
git add .
git commit -m "stash practice"

// やっぱり、↑ のコミットは消したいな、、

// "stash practice"のコミット番号をコピペ
git log
git revert コミット番号

すると、確認がターミナルに出ると思うので、「Ctrl + X」で閉じると、ファイルは以下の状態になっていると思います。

これで”stash practice”の変更内容が打ち消せていることが分かりました。

reset

resetはrevertと同じく、コミットを取り消したい時に使います。revertとは違い、指定された状態にリセットすることが可能となります。

resetで主に使用する3種類を紹介します。

①soft:コミットしたという事実だけが消える。ワークツリーやインデックスのステージ状況はコミット前と比べて変わらない。

git reset --soft

②mixed:コミットとステージした内容が消える。コミット前にステージしていた変更点は、ワークツリーに反映される。

git reset --mixed
// もしくは↓
git reset 

③hard:コミットしていない変更がすべて消える。まっさらになる。

git reset --hard

上記3種類をシチュエーションによって使い分けます。

今回はgit resetのデフォルト動作であるmixedを試してみましょう。(自由に他のコマンドも試してもらって大丈夫です!)

// masterブランチに移動する
git checkout master

// 新しいブランチbranch_resetを作成しチェックアウト
git checkout -b branch_reset

// "reset test string"という文字列を追加し、ステージ→コミット
echo "reset test string" >> file01
git add .
git commit -m "reset test"

// 巻き戻したい箇所のコミット番号を確認
git log

一番上にreset testのコミット、その下にその前のコミットが出てきます。

今回は「reset testを取り消す」ことがしたいので、すなわち、「1bc373aba9e743aef4c6521c0e2d1982c69da280」のコミット番号まで戻りたいということになります。よって、以下のコマンドを実行します。

// コミットのハッシュ値は皆さんそれぞれのものを設定してください
git reset 1bc373aba9e743aef4c6521c0e2d1982c69da280

これで「1bc373aba9e743aef4c6521c0e2d1982c69da280」までのコミットは取り消せたことになっています。差分を確認してみましょう。

git diff

コミットしていた”reset test string”の文字列が、ステージする前の状態で追加されています。git reset のデフォルトの動きは- -mixedの動きだったので、期待通り、変更点がワークツリーに反映された状態になっています。

※補足

resetとは別の話にはなりますが、ワークツリーの変更をリセットしたい時に下記のコマンドが使えます。

// ワークツリーの変更点をまとめてリセットする
git checkout .

補足:revertとresetの注意点

  • reset、revertを使用していいかはプロジェクトの規則による。

→正しく使用すれば大変便利な機能ですが、間違えて使うと変更履歴を改変してしまうこともあります。ゆえに、プロジェクトでresetやrevertの使用が禁止されている場合があります。

05リモート関連のGitコマンド

ここまでで、主にローカルリポジトリで使用するGitコマンドを紹介してきました。

次に、リモートリポジトリに関連するGitコマンドを紹介します。

これまで説明したように、ソースコードをサーバで共有する際、そのサーバ上に存在するリポジトリを「リモートリポジトリ」と呼びます。

この教材で実際に手を動かしてもらうことも考えましたが、今回はテキストのみにします。

最後ので課題をする際にリモートリポジトリを使うので、その時に実践しもらいます。

それでは、リモートリポジトリ関連で使用するGitコマンドを紹介していきます。

冒頭で、Gitのリポジトリには

  • リモートリポジトリ
  • ローカルリポジトリ

の2種類があると説明しましたが、さらにローカルリポジトリの内部では、

  • ローカルブランチ
  • トラッキングブランチ

の2つのブランチがあります。

トラッキングブランチは、リモートブランチの変化に追従するようになっており、ローカルブランチとリモートブランチを結びつける役割を担っています。(ローカルリポジトリの図とはまた別なので、混合しないように注意してください!

pull

「git pull」コマンドは、リモートリポジトリの更新内容を、任意のローカルブランチに取り込むためのコマンドです。

// 引数に何も指定しない場合は、最後に取得したリモートリポジトリが持つ最新の情報を取得する。
git pull

// 引数を正しく書く必要があるなら下記
git pull origin ブランチ名

なお、git pullは下記のGitコマンドの合わせ技です。

git fetch
git merge origin/取り込みたいブランチ名

push

次にpushです。pushは、ローカルブランチでcommitした内容を、トラッキングブランチとリモートブランチ反映させるためのコマンドです。

git push origin/リモートに反映させたいブランチ名

※「origin/リモートに反映させたいブランチ名」の箇所は、省略できる場合があります。毎回ブランチ名を打つことが一番堅調ではありますが、もし省略したい!という人は調べて使ってみてください。

(参考)

【Git】git push 〜引数を省略した時の挙動〜 – Qiita

Gitを業務で使用する時に、注意すること

①リモートに関連するコマンドには特に注意が必要

ローカルに関するコマンドをどれだけ実行しても、影響があるのは自分のみです。しかし、リモートに関するコマンドでミスをすると、プロジェクト全体に影響が出る可能性があります。

なので、「自分で実行する自信がないコマンド」は必ずチームの人や先輩に見てもらいながら、実行するようにしてください。

②コンフリクトを起こさないような運用を意識する

Gitの運用をする中で、ソースコードがおかしい状態になってしまう原因の1つに「コンフリクト解消のミス」があります。なので、コンフリクト解消を失敗しないというよりは、そもそもコンフリクトを起こさないようなやり方に工夫する必要があります。

例を挙げると、

  • リモートリポジトリの変更内容を頻繁に取り込むようにする。
  • プルリクエストを出すときに、同じような場所を触っているプログラマにもレビューしてもらい、自分がどの場所を触っているか周知する。
  • 今どの部分の開発が行われているのかを常に理解しておき、自分の作業がコンフリクトを生まないか意識する。

Githubのアカウント作成

続いて、課題を提出するためにGithubのアカウントを作成します。

まず、下記リンクにアクセスして下さい。

GitHub: Let’s build from here

そして、右上にある「Sign up」をクリックします。

次画面でアカウント情報の入力を求められるので、順番に入力して”Continue”を押下します。

(一番下の質問は、「アップデートやお知らせのメール通知が欲しいかどうか」という意味です。欲しい場合は”y”、不要な場合は”n”を入力してください。)

次に、ユーザが本当に人間かどうかの検証(CAPTCHA)が行われます。”Verify”を押下してください。

このケースは、「左の手の画像が指さしてるのと同じ方向に、右の動物の画像の顔を向けてください。」というものです。矢印をクリックして同じ方向に合わせて”Submit”を押下します。

テストをクリアすると、”Create account”のボタンが現れるので、押下します。

この後はアンケートが続くので、任意で入力してください。入力しない場合は画面下部の”Skip persnalization”を押下してください。

次もアンケートなので任意です。

下記のような画面に移動したら、設定完了です。

06Githubにソースコードを反映する

ここからは、Githubのリポジトリにソースコードを反映していきましょう。

個人アクセストークンを作成する

現在、Githubでは認証にパスワードなどではなく、個人アクセストークン(personal access token)が必要となります。

下記の手順を実行し、トークンを取得しましょう。

①メニューから「Settings」を選択

②左のメニューから「Developer settings」を選択

③「Personal access tokens」→「Tokens (classic)」→「Generate a personal access token」を選択

④次の画面では、作成するトークンの設定を行います。

Note=トークンの名前(自分の好きな名前にしてください。ここでは”myToken”と設定してます。)

Expiration=トークンの有効期限を設定。選択肢の中で最長の「90日間」を設定してください。

Select scopes=トークンに設定するスコープを選択します。今回は「repo」と「gist」にチェックを入れてください。

上記全て入力完了したら、「Generate token」をクリックします。

⑤作成されたトークンが表示されます。

※このトークンは現在表示されている画面でしか確認できません。必ずどこかに控えるようにして下さい。

これで個人アクセストークンの設定は完了です。

リポジトリにソースコードを反映する

続いて、ローカルのソースコードをリモートリポジトリに反映させます。

この後のプロセスは、各教材でリモートにリポジトリを作成しなければいけなくなった時に参照して欲しいものなので、今実行する必要はありません。

①ホーム画面のStart a new repositoryから「リポジトリの名前を入力(ここではtest-make-repositoryに設定)」「Private」→「Create a new repository」を選択します。

補足:今回は課題をPublicにしておく必要が特にないのでPrivateを選択しますが、今後は必要に応じて選ぶようにして下さい。

②ローカルリポジトリにリモートリポジトリを登録する。

次の画面が下記のようになり、「…or push an existing repository from the command line(既にローカルにリポジトリが存在してる場合のコマンド一覧)」に記載されているコマンドを順に実行します。

※リモートリポジトリに追加する箇所のみキャプチャと異なるので注意してください。

// ローカルリポジトリに移動
cd ローカルリポジトリへのパス
// ローカルリポジトリにリモートリポジトリを追加
git remote add origin <https://ユーザ名:個人アクセストークン@github.com/ユーザ名/test-make-repository.git>
// masterブランチをmainブランチに名称変更
git branch -M main
// リモートリポジトリのmainブランチにプッシュ
git push -u origin main

③Githubのページをリロード

ページをリロードすると、ローカルのリポジトリがリモートに反映されている状態になります。
これでリモートリポジトリにソースコードを反映することができました。

07課題

以下の手順に従って、課題を行ってください。

①mainブランチから新しいブランチを作成する。(名前は任意です)

②新しいブランチで、file01の文言をすべて削除し、「Git課題提出」という文言に書き換える。

③新しいブランチで、課題提出日を記載したfile02を追加する。

④差分を確認してコミットする。

⑤新しいブランチをmainブランチにマージする。

⑥mainブランチをプッシュする。


投稿日

カテゴリー:

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です