勉強日記

チラ裏

【git】masterからトピックを切っていたと思ったら、いつのまにかトピックから切っていた話【origin masterにpushするな】


あ…ありのまま 今 起こった事を話すぜ!

「おれは masterからトピックを切っていたと思ったら いつのまにかトピックから切っていた」

f:id:wand_ta:20191207004058p:plain

  • ※ masterは適宜develop等に読み替えてください
  • ※ developはありましたが無くなりました
    • (未リリースだしまあ妥当)

TL;DR

  • PR(MR)作れ
  • 次点でgit merge <branch> --no-ffしろ
  • タイトルは半分釣り
    • トピックをトピックから切ったように見えるだけ

ぜんてい

gitを用いた開発では、「ブランチ」が開発の単位となります。

いろいろな流儀がありますが、

  1. 幹から枝を生やして (トピックブランチ作成)
  2. 枝の上で作業をし (トピックブランチにコミット)
  3. 枝の作業を幹に戻す (トピックブランチを統合ブランチにマージ)

という大まかな流れは同じかと思います。

こうして形成されるのがコミットグラフです。

ローカルのgitコマンドやGUIツールで確認できますし、
GitHubGitLabといったGitホスティングサービスを利用している場合、Webブラウザ上でも確認できます。

f:id:wand_ta:20191206235048p:plain

さてGitホスティングサービスを利用する場合、

「3. トピックブランチを統合ブランチにマージ」

ホスティングサービス上で行うのが普通です。

トピックブランチをリモート(ホスティングサービス)にpushしたのち、

  • GitHubならPull Request
  • GitLabならMerge Request

を発行し、マージを実行します。

f:id:wand_ta:20191206235230p:plain

f:id:wand_ta:20191206235239p:plain

リモートの更新をローカルのトピックブランチに取り込む

さてGitホスティングサービスを利用する場合、

「3. トピックブランチを統合ブランチにマージ」

ホスティングサービス上で行うのが普通です。

逆はこの限りではありません。ローカルでマージするのが普通だと思います。(要出典)

いま、リモートのコミットグラフはこんな形:

f:id:wand_ta:20191207001044p:plain

ここで、コミットaからブランチfeature/Xを切って作業している人がいたとします

f:id:wand_ta:20191207010208p:plain

その人はリモートの最新のmasterを取り込みたいので、git fetchします:

f:id:wand_ta:20191207004444p:plain

ローカルのリモート追跡ブランチorigin/masterリモートのmasterが降ってきました。

「さあfeature/Xorigin/masterをマージするぞ!」

と、ここまではまあ普通です。
(merge/rebase宗教論争については触れません)

git checkout feature/X
git merge origin/master

f:id:wand_ta:20191207004652p:plain

NG: ローカルでmasterを更新してリモートにpushする

git checkout master
git merge feature/X

f:id:wand_ta:20191207004908p:plain

git push origin master

f:id:wand_ta:20191207005116p:plain

これはいけない。

masterがなるべく真っ直ぐになるようにコミットグラフが歪められて、こうなる

f:id:wand_ta:20191207005257p:plain

feature/A, feature/B「トピックブランチからトピックブランチを切った」ような珍妙な形になるわけです

f:id:wand_ta:20191207005419p:plain
あーあ

模範解答: Pull Request (Merge Request) を発行する

これに尽きる

次点: git merge 時、--no-ffオプションを付ける

開発者全員がPR(MR)を発行してくれるのは理想郷です。

偉い人が

「俺がmasterだ!!」

とばかりにgit push origin masterしてしまうこともあると思います。
そんなケースでもコミットグラフの治安を守るには、
git mergeコマンドの--no-ffオプションが有用です:

git checkout master
git merge feature/X --no-ff

f:id:wand_ta:20191207010926p:plain

git push origin master

f:id:wand_ta:20191207011002p:plain
世界は救われた

--no-ffとは、「no fast-forward」の意味。

fast-forwardとはマージの一種で、超ざっくりいうと

「差分がない場合はコミットを作成しない」

です。

--no-ffはその否定(no)なので、「差分がなくてもコミットを作成する」の意味です。

上記のマルと矢印の絵でいうと、コミットzがno fast-forward commitにあたります。

qiita.com

configで強制することが可能なので、チームのルールに取り入れるとよいのかもしれない。

いやPR (MR)出せや!!!って話なんですけどね!!!!!!