【もりけん塾】gitコンフリクト勉強会②【画像たくさんでハンズオン再現】

Git

今日は、もりけん塾の「gitコンフリクト勉強会」のまとめ②です。

こんにちは。Webコーダーのharuです。

*わたしについて*
2歳0歳の育児をしながら、22時〜2時にプログラミングを独学しています。
2020.5.11~学習スタート
2020.8.10~実務でコーディングしています
HTML/CSS(SCSS)/jQuery/WordPressの学習中です。
これからもっと知識をつけていきたく、インプット・アウトプットを続けています。

 

//普段から学習していてわかったことや、気付きをログに残しています。
※認識の間違っている箇所があれば、ご教授いただけるとうれしいです!

gitコンフリクト勉強会ハンズオン②

前回の「gitコンフリクト勉強会①」に引き続き後編です。

今回は、GitHub上でコンフリクトが起きた場合のハンズオンを記録します。

前回の復習

まず「gitコンフリクト勉強会①」の簡単なおさらいです。

下手な図をもう一度失礼いたします..w

①feature/aをmainにmergeしたい
②mainブランチ(基本のhtml)と、feature/aブランチ(基本のhtml + 編集あり)に相違がある状態
③mergeを試みたらターミナルにCONFLICTの文字が出た
④VSCode上で相違部分を編集(どちらの変更を取り込むか決める)
⑤commitをしてコンフリクト解消!
コンフリクトのパターン①ですね。こちらを解消するまでをやりました。
前回の記事はこちらからどうぞ!

コンフリクトの環境をつくる

では、後編に入ります。今回は、前回とは違うコンフリクトの環境(パターン②)をつくっていきます。

①feature/aブランチで変更をcommitし、GitHub上でpull requestを出す
②mainにmergeする前に、mainで同箇所の編集があった
③双方のブランチで同箇所の内容に相違が起こっている

というケースです。GitHub上のコンフリクトということです!

さっそくコンフリクトを作っていきます。(これまた、おかしな話ですがw)

①feature/aブランチの確認

「①feature/aブランチで変更をcommitし、GitHub上でpull requestを出す」ですが、こちらは前回の勉強会まとめ①で既に作ってあります。

まとめ①の最後で、このように終わっていましたね。

pull requestを出したあと、mergeボタンは押さずに終わっていました。

 

②mainブランチの編集

次にmainブランチの用意です。こちらは「②feature/aがmainにmergeする前に、mainで同箇所の編集があった」という状態にしたいです。

さっそく、mainブランチでindex.htmlを編集していきます。

git checkout mainでmainブランチに移動します。

余談ですが、わたしはことあるごとに「git branch」をたたいて、今いるブランチ(currentブランチ)を確認しています。前職のJAL端末も、こんな黒いターミナルみたいなのに謎の言語を打ち込むのですが、そのときの確認確認の精神かもしれません..(苦笑)ブランチ間違えは今のところ1度もないです。

さて、下図のような状態でした。

<body>内の記述を変更してみます。

git add. とgit commit。

git push origin headでpush。これで、mainが一つ進んだ状態になりました。

GitHubで今の状態を確認してみます。先ほどのmainのpushで、commitメッセージの部分が”fix:index.html”に変わりました。

③feature/aブランチをさらに編集

今回は、feature/aブランチでpull requestを出した状態のまま、もう一つcommitを積んでみます。

これは、のちにやってみるrebaseのためです!

feature/aブランチに移動します。

一つ前に作業していたブランチに戻るときは

git checkout -

が使えます!
移動したいブランチ名がすっごい長いときとか便利です!

今のfeature/aの状態です。先ほどのmainの変更を、feature/aは知りません。

<body>内に<p>を追加してみます。

git add.→commit→pushします。

 

コンフリクトの確認

コンフリクトを確認していきます。GitHub上でpull requestのタブを選択。

feature/aブランチを選択。

feature/aにコンフリクトが発生しているという表示が出ています。

コンフリクト表示の上には、コミット履歴も載っていますね。

fix:conflict →コンフリクト解消後にコミットしてpull requestしていたもの
fix:add p tag →先ほどpタグを追加して積んだコミット
これら2つのコミットは、mainにはmergeができていない状態です。

なぜコンフリクトが起きているのか?

今、なぜコンフリクトが起きているのかというと、

mainが更新されたのに、それを取り込んでいないfeature/aブランチの変更がmainの変更とバッティングしているからです。gitはどちらを採用すれば良いのか迷っている状態です。

今回はmainの編集やpushを自分で行いましたが、共同開発に置き換えると「誰かが別ブランチで開発していたindex.htmlの変更をmainにmergeした」というシチュエーションです。

コンフリクトの解消方法

この場合の解決策は3つあります。

①GitHub上で解決
②git mergeする(勉強会まとめ①でやりました)
③git rebaseする
①のGitHub上の場合は
先ほどのpull requestのタブでみていた画面から、Resolve conflictsを選びます。(あっ、ここ勉強会の範囲外です..!余談です..!)

出てきたエディタで、変更を生かしたい部分を残し、不採用の部分は消します。最後にMark as resolvedを選択。これでmainにmergeができます。

 

今回はせっかくなので、③のrebaseで対応してみます!

rebaseについてはこちらでもアウトプットしています。もし良ければどうぞ!

rebase(リベース)でコンフリクトを解消する

rebaseはmergeと似ているのですが、コミット履歴の残り方が違います。

上記のアウトプット記事内の見にくい図ですが再掲します..

mergeの場合は、「b1/b2という別ブランチのコミット」をmainにmergeすることで「a5」というコミットが作られました。

rebaseで対応すると、下図のようにmergeコミットが作られないままb1/b2を積み上げることができます。結果自体はmergeと変わりませんコミット履歴がシンプルで見やすくなるため、開発現場では好まれるのだそうです。

$git rebase mainの流れはこんな感じです。

①git rebaseすると、feature/aブランチが切り離される
②mainのHEAD(最新のコミット)とfeature/aブランチのコミット(古いものから順に)が比較される
③コンフリクトを解消する→比較されていたfeature/aのコミットがHEADの上に追加される
④git rebase –continueでfeature/aブランチのコミット(2番目に古いもの)が比較される
⑤コンフリクトを解消する→比較されていたfeature/aのコミットがHEADの上に追加される
⑥git rebase –continueで対象のコミットがなくなるまで比較する
⑦比較するコミットがなくなったら新しい履歴の完成→pushする
という流れです。
実際にターミナルでrebaseしていきます。
実際の開発では、必ずmainの変更をpullして、リモートのmainを最新にしてからrebase作業を行います。今回は、自分でmainを変更していたため既に最新になっています。
git rebase [rebaseしたい先のブランチ名]

なので、feature/aブランチで、git rebase mainします。コンフリクトしてるので直してね、と出てきます。

index.htmlは自動的にこのような表示になります。

気をつけなければならないのは、前回の勉強会のmergeのときとはmainとfeature/aの位置が逆なことです。上がmain,下がfeature/aです。

実際には、どれを残してどれを消すのか自分でよく確認して変更します。今回は、「両方の変更を取り込む」を選択してみます。

さらにいい感じに編集して、下図のようになりました。

編集したら保存して、必ずgit add.します

git rebase –continueで、引き続きコミットの比較をしていきます。

あらたにindex.htmlにコンフリクトが表示されました。下のfeature/aの変更が「fix: add p tag」に変わっていてコミットが一つ進んだことがわかります。

どちらの変更も取り込み、下図のように編集します

保存→git add.します。続いて、git rebase –continueすると、applying: fix: add p tagと表示されて編集が終わりました。

ハンズオンでは、Successfullyと表示されるとあるのですが、わたしは表示されませんでした汗

(引用:もりけん先生のハンズオン資料)
しかし、わたしの状態でもrebaseはできていました。。

のちに、先生のgit configに「core.editor = /usr/local/bin/vim」という設定があることがわかり、おそらくこの設定のあるorないが原因ではないかという話になりましたが..まだ検証できていません。検証しましたら追記したいと思います。
SuccessfullyではなくApplyでも、git logでログが1本になっていれば、rebaseは成功しているので問題ありません。

ここまでで、合体したコミット履歴は完成しました。これらをfeature/aにpushする必要があります。

pushの際には、

//強制push
git push --force-with-lease origin head

が必要になります。単なる

git push --force origin head

を使ってしまうと、この間に別の人がfeature/aに変更を加えていた場合、上書きをしてしまいます;
–force-with-releaseをつけることで、push先に変更があった場合は警告を出してくれます。
それでは、git push –force-with-lease origin headします。

doneになりpushができたようなので、GitHub上で確認してみます。

fix: add p tagの先に、force-pushedの記述があればOKです。
先ほどコンフリクトの表示になっていた部分が、merge可能になっています。

mergeして変更を取り込めば、意図する通りに更新ができました。

もりけん先生の勉強会資料はこちらです✨

 

あとがき

お忙しい中、素早く資料を作ってくださり、ありがとうございました!!

ハンズオン、大変勉強になりました。rebaseまで経験できるとは思っていませんでした。

また、実務で使いつつ、gitを使いこなせるように練習していきます!

 

今日は以上です。
Thanks:師匠「もりけんさん」(@terrace_tec)

もりけんさんのHPはこちら

タイトルとURLをコピーしました