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

Git愚痴

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

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

20191207004058

  • ※ masterは適宜develop等に読み替えてください
  • ※ developはありましたが無くなりました

    • (未リリースだしまあ妥当)

TL;DR

  • PR(MR)作れ
  • 次点でgit merge <branch> --no-ffしろ
  • タイトルは半分釣り

    • トピックをトピックから切ったように見えるだけ

ぜんてい

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

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

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

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

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

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

20191206235048

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

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

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

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

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

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

20191206235230

20191206235239

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

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

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

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

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

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

20191207001044

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

20191207010208

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

20191207004444

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

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

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

git checkout feature/X
git merge origin/master

20191207004652

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

git checkout master
git merge feature/X

20191207004908

git push origin master

20191207005116

これはいけない。

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

20191207005257

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

![20191207005419](../../../imgs/20191207005419.png)
あーあ

模範解答: 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

20191207010926

git push origin master
![20191207011002](../../../imgs/20191207011002.png)
世界は救われた

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

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

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

です。

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

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

[https://qiita.com/nog/items/c79469afbf3e632f10a1#%E8%A8%AD%E5%AE%9A%E3%81%AB%E5%85%A5%E3%82%8C%E3%81%A6%E8%87%AA%E5%8B%95%E5%8C%96%E3%81%97%E3%82%88%E3%81%86:embed:cite]

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

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