まさ@ブログ書き込み中

自由に生きるための英語、プログラミング、考えごとについて色々書いています。

Gitをガチで使う

 

 

こんばんは、まさです。

 

仕事で開発をしていく中で、自分で気をつけなければならないなと思ったことはいくつかあったのですが、今日は特にGit(やGitHub)についてそう思うところがありました。

 

なので、今回はまさなりのGit Flowについてまとめていきたいと思います。間違っている可能性が大なのですが、なんとなーくまとめておきたかったので。

 

 

Git Flowとは

「Gitにおけるリポジトリのモデルのこと。こんなふうにブランチを切って運用していくと便利だよというワークフローのこと」らしいです。

 

この記事を念頭に話をしていきます。

qiita.com

 

まさのGit Flow

大まかに以下のブランチに分けて開発しています。

  • master
  • develop
  • feature/hoge

feature/hogeの"hoge"はなんでもいいってことです。

つまり、master,develop,featureブランチに分けて開発しているということです。

 

 

使い分け

 

master

マスターブランチ。これはとにかく「一番大切なやつ」のイメージです。だから、開発現場によって変わります。仕事ではprodcutionブランチとmasterブランチがあって、これは本来のgit flowのrelaseブランチとmasterブランチに対応するんだろうけど、まさにとってはどちらもmasterブランチです。

 

「何言っているんだ」って思われるかもしれないけど、「developブランチではない」という感じです。masterブランチにpushされる内容はprodcutionでも使われるでしょ、と思っています。

 

develop

featureブランチで作った機能が採用されたものが集まるブランチ。

 

本来のgit flowではfeatureブランチの開発が終わったらローカルのdevelopブランチに勝手にマージしてしまって、developブランチをpushしてプルリクを送る・・・って感じなんだろうけど、まさの場合はdevelopブランチこそプルリクを送った結果統合されるブランチです。

 

本来のGit(GitHub) Flowでmasterにマージするところを最悪の自体に備えたクッションとして用意した感じです。

 

ちなみに、仕事ではStaging(developブランチ)とProduction(prodcutionブランチ)とどちらもデプロイしています。Staging(developブランチ)は最終チェックのためにあります。

 

feature

このブランチは比較的自由に扱っていいブランチです。機能ごとにブランチを切ります。そして開発が終わったらdevelopにマージするためのプルリクエストを送ります。

 

ブランチ名はfeature/hogeです。わかりやすくかつ簡潔に示すために動詞+目的語でブランチ名をつけています。

例:feature/improve-login-view

 

 

ブランチの切り方が雑

とまあこういった前提で開発をしていったのですが、今回困ったポイントは僕が雑にブランチを切りすぎてローカルでのmergeやらdevelopでのmergeやらが複雑になってしまったことです。

 

いま思えば本当に豪快だよなっていう思うブランチの切り方。ブランチ切らなきゃって思った時が切りどきって感じ。これはもう迷言ですよ。迷言。

 

なのでdevelopやmasterブランチ放っておいてブランチからブランチを無作為に切るわ、AからBブランチ作った後にAブランチでコミットし始めるわ、それをBブランチでmergeしないわ・・・

 

その結果、プルリクの時にパニクってしまいました( ;∀;)

 

しかも最悪なのはローカルのブランチ同士でmergeした時にmergeすべき方とされるべき方をミスってたり・・・。 もううわあああああああああってなりました。

 

これが夕方の僕です。

 

 

どうすれば良かったの 

僕が大先輩の廣太くんに聞いたアドバイスや冒頭のサイトを参考にしながら「次からこうしよう」と思ったこと、確認する必要のあるコマンドを最後にまとめていきたいと思います。

 

developブランチから毎回ブランチ作ればいいんじゃない

プルリクがすぐに通ったり、レビューが来たりしてリモートのdevelopブランチが最新であれば毎度引っ張ってこればいいのですが、レビューが来る前にすぐに作業を続けたかったりする時があると思います。

 

その時は二つのパターンに分けて良くて、それは

  1. レビュー待ちの実装を踏まえて開発する場合
  2. レビュー待ちの実装とは別のところをいじる場合

 があります。

 

1の状況であれば、どのブランチから切るかを意識しておきながら(まさのようにアホみたいに何も考えないようなことがなければおk)最新featureブランチから新しいブランチを切って良いと思います。

 

ただし気をつけないといけないのはレビュー待ちのプルリクに修正が入った場合です。プルリク待ちのfeatureブランチをAとして、そのブランチから新しく切ったブランチをBとすると、レビューの結果Aブランチを修正した場合、Bブランチの内容も修正しなければなりません。

 

その時はBブランチがAブランチをmergeすればいいのです。これを忘れないようにしなければなりません。

# you are in B branch now
git merge A branch

 

2の状況であれば、developブランチから新しいfeatureブランチを切った方が懸命です。理由は二つあって、一つはdevelopブランチがベースなのでブランチ間の相互関係を気にせず安心してdevelopブランチにプルリクを投げられること、もう一つは別に最新ブランチから新しいブランチを切る必要がないことです。

 

2の状況ならdevelopブランチ以外から切る理由がないってことですな。

 

Gitコマンドをミスらなければ良かったんじゃない

後もう一つ改善点があるとすれば、僕のGitコマンドに対する理解度です。恥ずかしい話ですが、あまりにブランチを複雑に分岐させていたので、mergeする時にミスっていた可能性があります。

 

具体的には、4つくらいのブランチを適当に切っていた・・・といえば伝わるでしょうか。その時に分析するために使ったコマンドと共にコマンドをまとめていきます。

 

git log全部入り

git log --oneline --decorate --graph --branches --tags --remotes

 

これがわかりやすそう。git log全部入り - Qiitaによると、

  • --oneline: 1commit 1行のみログ表示
  • --decorate: branch名、tag名などの別名を表示
  • --graph: revision graphを表示
  • --branches: 他のbranchのlogも表示
  • --tags: tagを表示
  • --remotes: remote branchなどを表示

って意味らしい。これでブランチ間の関係性やログをチェックできる。

 

リモートブランチ(GitHubとか)との関係をいじくるときのコマンド

git branch -a

というコマンドでリモートにどんなブランチがあるかを確かめることができます。

 

git fetch

でリモートの最新の情報を更新することができます。

 

git checkout -b hoge_branch origin/hoge_branch

でリモートのhoge_branchを取って来ることができます。

 

また、僕の場合はローカルのブランチをごにょごにょしすぎてGitHubリポジトリとどれだけ差があるのか知りたくなって、以下のようなコマンドも駆使しました。

 

git diff HEAD^

これは前回のコミットとの差分を見るコマンドですね。

 

git diff 変更前のSHA..変更後のSHA

SHAとはgit reflogやGitHubのコミットに書いてある7桁のコミットID的なやつ。git logで出て来るコミットに振り分けられているID的なデータの最初の7桁でもあります。

 

また、SHA同士の間の".."は半角スペース" "でもいいみたいです。

 

残りはこれを参照したらよさそう。

忘れやすい人のための git diff チートシート - Qiita

 

僕はとにかくgit diff HEAD^したりgit diff HEAD@{}したりして一生懸命やっていました。

 

merge関連のコマンド

差分をマージ

git merge [branch_name] 

 

マージの取り消し

git merge --abort

GitHub上ではmergeをミスったらRevertというmerge前に戻すためのプルリクを投げて、再度mergeさせることによって取り消しを行うことになります。

 

残りはこのサイトが詳しそう。

【Git】基本コマンド - Qiita

 

先ほど言った通り、僕の場合は(例えば )AブランチとBブランチそれぞれが独走して(別々のコードを書いて)変更が起きていたのですが、その場合はどちらがどちらをmergeしようと(変更点が異なるので)コンフリクトも何も起きないはずです。

 

いま思えば当たり前のことなのですが、今日の僕は何を思ったのかこんなツイートをしていました。

精進しなきゃ。

 

git pullとgit fetchとgit clone

それぞれの違いについてざっくりまとめると

  • git fetchはさっき言った通り、リモートの情報(データ)を取って来るだけ
  • git pullはgit fetchとgit merge origin/masterをやってくれる(こわい)
  • git cloneはリポジトリを複製する 

 

まじか。これまで死ぬほど「git pullしてこればいいね」ってドヤ顔で言ってたけど、それは漠然と「リモートから取って来る」ことをイメージしていただけで「git pullしているリポジトリにorigin/masterをmergeする」といった風にしっかり考えたことなかったです。

 

あと今回のように知識をまとめていなかった6時間前くらいのまさは「既存のディレクトリにgit cloneできないいいいい」とか言ってたけど冷静に考えて「何でそれする必要あるの」っていうことだったんですね。git checkoutを使えよ、と。

 

このサイトを参照しました。

fetch と pullの違い - Qiita

 

 

最初からちゃんとしていればこんなに焦ることはない

当たり前なのですが、最初からブランチの切り方とか、Gitコマンドの使い方の基本を抑えてたりもう少し慎重に開発していたら僕に起きた問題 には出会わないのかもしれません。

 

でもまあ遅かれ早かれ新人が通る道として良い学びになったと前向きに捉えつつ、今回はこのブログを書きました。

 

まとめ

  • 考えてブランチ切ろう
  • Gitコマンドはバンバン叩くと痛い目見る
  • まだ慌てるような時間じゃないから絡まったGitログをみてイライラするのはやめよう

 

今回はここまで。ではまた。