0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GitのFast Forwardの動作を確認してみる

Last updated at Posted at 2020-09-20

はじめに

前回の記事からの続き。
理想を追い求めたCI/CDパイプラインでは環境とブランチが1対1に紐付き、その間では1つのコンテナベースを渡り歩かせるのが原則となっているため、Commitとコンテナベースを一意に紐付ける識別子が必要になる。一方で、GitLabではデフォルトのマージはmergeCommitとなり、CommitIDが都度作られてしまうことから、コンテナべベースを一意に識別するためには、外部から識別子を渡してあげなければいけない。外部から渡すということは人力の作業が増え、自動化原則から外れてしまう。対応するには、mergeCommitをしないFast Forwardなマージを考える必要がある。

Fast Forwardなマージとは

GitLab Docs参照。
なぜか日本語ドキュメントでもこのパートは訳されていないけど……。

さらに、Fast ForwardとNon Fast Forwardの違いをしっかり説明してくれているのが以下のブログ
「こわくない Git」というスライドを発表しました
ちょうわかりやすい。Gitに苦手意識のあるすべての人が読んでおくと良いと思った。

Fast Forwardでは、たしかにスライド中にある「マージをしたという記録が残らない」「マージが取り消しづらい」がデメリットになってしまうので、これについては、「ちゃんとタグで記録残していきましょう」なんだろうな……。

実際に動かしてみる

さて、実際に以下のようなGitLab Flowを運用していると仮定して実験してみる。

  • masterブランチ
  • productionブランチ
  • 開発時 feature/issueXX ブランチ

単一featureブランチからの単純なFast Forward

初期状態

feature/issue01 では b.txt の追加と a.txt の修正をした状態から、productionへの反映をやってみよう。
Commitグラフは以下のような状態がスタートだ。

キャプチャ1.png

masterへのマージ

ブランチからマージリクエストを送り、Fast Forwardなマージを行う。

キャプチャ2.png

たしかに、マージの記録が非常に分かりにくいが、ブランチはfeature/issue01と同じCommitIDに移動している。

productionへのマージ

ブランチからのマージではないので操作方法に一瞬悩むが、新規のマージリクエストからであれば、masterブランチからのマージリクエストを作成できるので、そこから行う。

キャプチャ3.png

これで、production も master と同じところまで進んだ状態になる。

さて、ここまでは基本的なFast Forwardの動作なので特に考えることはないはずだ。

複数featureブランチからのFast Forward

では、複数人で開発を行っていて、feature ブランチが並走している場合はどうなるだろう?
一度、これまでの開発の feature は削除して新たに feature/issue02、feature/issue03 を作る。

初期状態

以下の開発を行ったと仮定する。

  • feature/issue02: c.txtの追加
  • feature/issue03: b.txtの修正

マージ前のCommitグラフは以下のようになる。

キャプチャ4.png

masterへのマージ

まずは、feature/issue02 をマージする。

キャプチャ5.png

Commitグラフは上記のようになり、c.txt は追加されているが、b.txt の修正は取り込まれていない状態だ。

キャプチャ6.png

ここから更に、feature/issue03 をマージする。すると…

キャプチャ7.png

この場合はファイルが競合していなくても、どうやら Fast Forward なマージはできないようだ。
Rebase をしてみよう。

キャプチャ8.png

なんかそれっぽくマージされたように見える。
リポジトリの中身は問題ないだろうか。

キャプチャ9.png

ちゃんと feature/issue02 と feature/issue03 が取り込まれている!

productionへのマージ

ここまでできていれば一安心で、production へのマージは単一featureブランチと同じように実施可能だ。

キャプチャ10.png

先に進んでいるmasterブランチの過去のCommitIDからproductionブランチにマージする

feature/issue04 ブランチの開発については master ブランチへのマージまで完了していてあとは production 環境にデプロイするだけなのだけど、もろもろの事情でちょっと待って、と言われてるところに次の feature/issue05 ブランチの開発が来ていて stage 環境にはデプロイしなきゃいけないからとりあえず master ブランチは進めないと、といった状況になった場合の方法論(今回は stage 環境ないけど…)。
さらに考えると、この stage 環境での開発を先に production 環境にデプロイしないとといけないケースも想定できるが、そこまでいくともはや Fast Forward は諦めて別の方法を考えた方が良いと思うので、一旦除外する。

初期状態

以下の開発を行ったと仮定する。

  • feature/issue04: d.txtの追加、c.txtの追加 → masterブランチへのマージ
  • feature/issue05: 上記の後、e.txtの追加、d.txtの修正 → masterブランチへのマージ

Commitツリーは以下の状態。

キャプチャ11.png

feature/issue04ブランチは以下の状態。

キャプチャ12.png

masterブランチおよびfeature/issue05ブランチは以下の状態。

キャプチャ13.png

productionへのマージ

さて、上記の master ブランチからマージをかけてしまうと、当然 master ブランチの最新の状態になってしまう。今回のケースであれば、まだ feature/issue04 が残っているから、そこからマージしてしまうというのも一つの手段だ。ただし、今回は分かりやすくするために残しているが、通常は feature ブランチは、master ブランチへのマージが完了した時点で消してしまうため、この手段が使えない。

こういう時は、タグを使おう。
と言うか、冒頭に書いたように、Fast Forwardなマージコミットの場合、マージした際にタグをつけておかないとワケが分からなくなるため、本来はそのタイミングで付与しておくべきだろう。

キャプチャ14.png

タグを作ったら、そこからブランチを作ることができる。

キャプチャ15.png

ブランチができれば、後は普通にブランチから production ブランチにマージすれば良い。

キャプチャ16.png

production ブランチの内容も、しっかり feature/issue04 のみが取り込まれ、feature/issue05 は入っていない状態になっている。

キャプチャ17.png

production 環境での不具合発生時にどう対応するか

master ブランチが進んでいない場合

仮に、次の開発が進んでいたとしても、まだ feature ブランチでの開発を行っているだけで、master ブランチへのマージが行われていない場合は、複数featureブランチからのFast Forwardと同じように行うだけである。

  1. hotfix ブランチの作成
  2. master ブランチへのFast Forwardなマージ
  3. production ブランチへのFast Forwardなマージ
  4. その後、feature ブランチからのマージでは rebase が発生するので、充分注意してマージする

master ブランチが進んでいる場合

初期状態

厄介なのは、既に master ブランチに次の開発がマージされてしまっている以下のケースである。

キャプチャ18.png

このケースでは、既に以下の開発が master ブランチに取り込まれている状態で、過去の開発のファイル a.txt に不具合が見つかったと仮定する。

  • feature/issue06: f.txtの追加

この時は、production 環境へのデプロイが必要だが、まだ feature/issue06 を取り込んではいけない。
仕方がないので、一旦 production を真として進めるしかないだろう。

hotfix ブランチの作成

production ブランチを元に、hotfix ブランチを作成して、a.txt を修正する。
当然のことながら、feature/issue06 はまだ取り込まれていない。

キャプチャ19.png

キャプチャ20.png

この状態でパイプラインを起動させる必要があるため、普段 master ブランチで開発環境にデプロイをしているのであれば、設定変更をするか、パイプラインをクローンして開発環境でテストを行う。

hotfix ブランチを production ブランチに Fast Forward でマージ

テストが終わったら、hotfix から production にマージをする。
production は既にパイプラインがあるはずなので、ここは通常の操作で良いだろう。

キャプチャ21.png

キャプチャ22.png

これで、production 環境は無事修正された。
後始末で、masterへのマージを忘れないようにしよう。

hotfix ブランチを master ブランチに rebase でマージ

ブランチが途中で完全に分岐してしまっているため、ここは rebase になってしまうのは致し方ない。
ただし、ここで気を付けなければいけないのは、必ずproduction ブランチではなくhotfixブランチをマージすること。
rebase したタイミングでproductionブランチにcommitが発生するため、パイプラインが起動してしまう上に、開発中の feature/issue06 が取り込まれてしまう。

hotfix ブランチを rebase すると、ブランチツリーは以下の状態になる。

キャプチャ23.png

キャプチャ24.png

この状態で、master ブランチを Fast Forward でマージすることで、master は feature/issue06 と hotfix/bug01 を取り込んだ状態にできる。

キャプチャ25.png

production ブランチを master ブランチに合流させる

最後に、feature/issue06 の開発完了時に、production ブランチに反映させなければいけないが、ここが曲者である。ブランチが途中で分岐してしまっているため、どうしても rebase が発生してしまう。しかし、rebase でいきなり production ブランチを更新してデプロイのパイプラインが実行されるのはリスクが高い。

ここは、ちゃんと実績のある資材を動かすために、多少強引であるが、production ブランチを master ブランチに付け替えてあげよう。

$ git reset --hard [masterブランチのCommitIDのハッシュ]

なにげにこれはかなり危険な操作なので、ちゃんとGitを理解している人とレビューしながら操作した方が良い。

これを行うことで、

キャプチャ26.png

といった具合で master ブランチに production ブランチが合流したことになる。

0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?