LoginSignup
1
0

More than 3 years have passed since last update.

git基礎(実践)

Posted at

git基礎(実践)

環境:Windows10,WSL Ubuntu 18.04, Git2.28.0, (Backlog git)
言語:C++(好きな言語使ってください)
実際に、理論編の話を、1からgitで開発していきます。

§1 gitリポジトリを作成する

1.ディレクトリを作成する

gitリポジトリを作成するには、ディレクトリが必要です。/home/[user]/以下に"demo"ディレクトリを作成します。
Ubuntuでは、mkdirでディレクトリを作成できます。
eac69da3-7747-4274-a8d3-2dc5803214d7.gif

git initコマンドが成功すると、.gitディレクトリ(隠し)が作成されます。

ls -la .git

として、.gitのフォルダ構成をみると以下のようになっています。
image.png

オブジェクトと参照の存在が確認できます。(objectsとrefs)
この2つのディレクトリに、全てのリポジトリデータがこの2つのディレクトリの中に格納されています。

git hlep init

と打ち込んでみましょう。そうすると、initコマンドの詳細が見ることができます。
image.png

git status

と打ち込んでみましょう。そうすると、今何が起こっているのかを確認することができます。
image.png

現状は、なにも操作を行っていないので、"No commits yet"となっています。
git基礎(理論)で、そのコマンドがどのような操作(DAGであるgitの履歴に対する処理)を行っているのかを考えてみましょうと、書きましたが、現状はDAGがただ始点のみで、辺が張られていないので、No commits yetとなっています。

2.ファイルを追加する

gitリポジトリにファイルを追加してみましょう!
"hello world"という文字列内容の書かれた、hello.txtを作成します。
image.png

demo\<root directry>
|
+-hello.txt(blob, contents="hello world")

さて、これを新しいスナップショットとして、このディレクトリの一番最初の状態として、変更履歴を保存します。

git snapshot

git には上のコマンドは存在しません。
現在のディレクトリ全てをスナップショットとして保存するようなコマンドはありません。理由はいくつかありますが、gitは、次にどのような変更をスナップショットに加えるかというオプションを与えて、より柔軟な管理方法を提供するためです。
gitは、ステージングという概念を持っています。gitは、次のスナップショットにどのような変更を加えるかというオプションを与えます。
image.png

git status

上から、gitは、リポジトリに変更があったことを認識していますが、それをスナップショットに加えることはしていません。
なぜなら、これは、ユーザにこの変更を次のスナップショットに加えるか、否かのオプションを与えるためです。

git add hello.txt

と打つと、
image.png

変更が追加されました。これは、スナップショット(git commit)にこの変更を加えるという意味です。

git commit

を打ってみましょう。
888f18ce-882e-4860-9b2f-61c3adc1f58d.gif

デフォルトエディタが立ち上がり、コミットメッセージを入力します。コミットメッセージは、あとからなぜその変更を加えたのかが一目でわかるようなメッセージであるべきです。しかし、今回はテストなので"Add hello.txt"としています。
よいコミットメッセージの書き方を載せておきます。OSSなどで、チーム開発するときは、意味のあるメッセージを残すように心がけましょう!
Write good commit messages!
Even more reasons to write good commit messages!
image.png

commitに成功すると、上のようになります。
ここで、[master(root-commit)f75edd5]のf75edd5は今のcommitのハッシュ値です。ここでのcommitは正確には、treeのポインタを保持しています。

git cat-file -p f75edd5

と打つと、
image.png

treeのハッシュ値が保持されています・・・。
更に、

git cat-file -p 68aba62e560c0ebc3396e8ae9335232cd93a3f60
git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad

と打つと、上のようにhello.txtの変更内容がわかります。
つまり、"git commit"は、参照の集合をスナップショットとして保存していることがわかります。

3.ログを確認する

gitのlogコマンドは、変更履歴を視覚的にわかりやすく表示してくれます。

git log

image.png

上のように、git log は変更履歴を表示してくれます。現状は、一つのcommitしかないので、一つの変更履歴のみ表示されます。
新しくcommitしてみましょう。

echo "another line" >> hello.tx
git add hello.txt
git commit -m "Add another line in hello.txt
git log

image.png

現状は、2つのコミットしかないですが、git log になんのオプションも書かないと線形的に書かれます。

git log --all --graph --decorate

のようにオプションを付けることでより視覚的にわかりやすくログを表示してくれます。
image.png

左辺の赤い線がグラフの辺を表しています

4.オブジェクトと参照

次は、
image.png

これを見ていきましょう。
git基礎(理論)でも紹介しましたが、gitではハッシュ関数によって暗号化された参照を人間にとってわかりやすくマッピングします。
masterとは、gitリポジトリを作成したときに必ず作成される、最新のメインブランチの特別な参照です。今回は、masterは、 3800812708f08da07746b7800b880050590ee71eのポインタです。
HEADも、gitリポジトリの特別な参照です。HEADは、今自分がいる場所を示しています。

5.変更履歴を遷移する

HEADは、今どこにいるかを示す参照でした。
いまは、
image.png

 commit 3800812708f08da07746b7800b880050590ee71e (HEAD -> master)

ここにいます。

git checkout f75edd575792baddf801cf3f7e1479f1b9a6da14

とすると変更履歴を遡ります。
image.png
image.png

この状態で、"cat hello.txt"とすると、hello.txtに"another line"を加える前の状態に戻ります。
また、HEAD(今いる場所)が、ひとつ前のスナップショットに戻っていることに注目してください!!

git checkout master

とすると、最新のスナップショットの場所に戻ります。(masterは、最新のスナップショットの参照)
image.png

image.png

hello.txtも、最新の状態になっていることが確認できます。
git add コマンドを行わずに、git checkoutを行うと変更履歴が保存されていない状態で、状態遷移をすると、blobやtreeが書き換わってしまうので、注意してください。

6.diffコマンド

最新のスナップショットの状態で、hello.txtの内容を書き換えてみましょう
image.png

image.png

git diff コマンドでは、現在のスナップショット(HEAD)から今の状態で、変更された内容を出力します。
オプションとして、

git diff ポインタ1 ポインタ2 ファイル名

でポインタ1の示すスナップショットと、ポインタ2の示すスナップショットのファイルの変更された内容を出力します。
image.png

7.ブランチ

"Hello" を出力する簡単なC++(好きな言語でいいです)を作成します。
image.png

そうして、新しく、"cat"ブランチを作成します。

git checkout -b cat

image.png

新しいブランチ"cat"が作成されたのが見えます。
HEADがさしているmasterが現在のブランチで、新しいスナップショットを作成したときは、masterに変更履歴が加えられます。

git checkout cat

とすると、ブランチがcatになります。
image.png

animal.cppをコマンドライン引数で、"cat"を持つとき、"Meow!"と標準出力するように書き換えます。
image.png

git にスナップショットを保存します。
image.png

catブランチにcat関数を加えたので、masterブランチとは違う状態にいます。
このような状態を,parallel programmingと言ったりします。
同様にして、dogブランチを追加して、コマンドライン引数にdogを持つとき、"Woof!"と出力するように書き換えます。
image.png
image.png
image.png

上のログを見るとグラフ構造がよくわかると思います。これもgit log オプションのおかげです。
図を書くと

〇<---〇<---〇(master)+〇cat
        |
       +〇dog(HEAD)

のようにmasterから、dog,catが分裂しています。

これから、masterにdog,catブランチを統合していきます。
まず、HEADをmasterにします。
image.png

その後、

git merge cat

でcatブランチをマージします。
image.png
この状態で、animal.cppはcatブランチのanimal.cppとなっています。
image.png
次に、dogブランチをマージします。
image.png

CONFLICTが出ました。これは、二つの平行するブランチのマージの衝突が起こったことを意味します。Auto-mergingが行われていますが、この衝突が起こった時はこの課題を修正することが必要です。このような、マージの衝突が起こった場合に使うツールがgitに入っています。それが、git mergetoolです。
image.png
image.png

このツールを使うと、上のようにマージの衝突の詳細を比較してくれます。
このツールを使って、修正を施していきます。
image.png

今回は、main関数内のif文をelse ifに書き換える等の修正を施さなければならないです。
そのあと、gitにmergeを続けてもらいます。

git merge --continue

image.png

〇<---〇<---〇(master)+〇cat---
        |         |<---〇master(cat,dogマージ)
        +〇dog(HEAD)---

マージが成功すると、このようなログになります。
image.png

image.png

(実行するとこんな感じ)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0