LoginSignup
9
3

More than 5 years have passed since last update.

状況で使い分けるGit術 前編

Last updated at Posted at 2018-05-28

Qiita内にも数多に存在しているGitの記事。
コマンド然り、奥義や裏ワザもたくさんありますが正直全部覚えなくても開発はできます。

ただ、「機能はわかるけど使い所がわからない」という場合はあるかと思いますので、ある程度厳選してフィクションに沿った状況に応じた使い分けを残します。
※フィクションですよ

設定

  • 月君 ... 慣れてくると調子に乗りミスをする常習犯。SouceTree崇拝者。
  • A先輩 ... 開発チームメンバーの先輩。デキる意識高い系。
  • P上司 ... 二人の上司。通称:レビューの鬼。

前提

  • GitFlowを使用している
  • Macでvimを使用している

コンフリクト(競合)が発生

月君「ア"ッ!!プルリクだしたのにdevelopブランチとコンフリクトしてる…。A先輩がmergeしたpaisen_Aブランチが原因か。」

スクリーンショット 2018-05-28 17.32.21.png

方法1 mergeで対応する

月君「私のmoon_devブランチにdevelopブランチをmergeして発生するコンフリクトを直そう」

月君は「〜動きをチェックするための〜」を「〜動きをチェックしたいがための〜」に変更しましたが、
A先輩は「〜プロジェクト。」を「〜プロジェクトだよ。」にしていたようです。

スクリーンショット 2018-05-28 17.37.50.png

月君「よし、コンフリクトを解消してmoon_devブランチでマージコミットを作成したぞ。これでOKだ。」

コミット履歴は雑多になりましたが、コンフリクトは解決でき、無事マージされました。

スクリーンショット 2018-05-28 17.53.32.png

※マージ先のブランチでコンフリクト解消コミットを作成する方法もあります
※GithubなどはコンフリクトをWeb上で修正できます。便利ですね

方法2 rebaseで対応する

月君「私のmoon_devブランチにdevelopブランチをrebaseして発生するコンフリクトを直そう」

rebaseでコンフリクト解消したら、git addでインデックスに登録し、--continueを叩きます。

$ (moon_dev) git rebase --continue
Applying: 変更しました。

月君「よし、じゃあtopicブランチをプッシュしよう。」

$ (moon_dev) git push origin moon_dev

error: failed to push some refs to 'git@github.com:hogehoge/hugahuga.git'
...

月君「謎のエラーだ!」

月君はテンパったようですが、このエラーはrebaseにしてコミット履歴がdevelopブランチにくっついた事により、git logの整合性が取れないというエラーでした。
スクリーンショット 2018-05-28 18.07.37.png
↑moon_devのリモートブランチとローカルブランチのグラフが全く違います。

こういう時は強制オプション -fを使用します。(賛否両論有)

$ (moon_dev) git push -f origin moon_dev

スクリーンショット 2018-05-28 18.11.50.png

moon_devリモートブランチが強制的に変更されました。

月君「rebaseの方がコミット履歴綺麗になるじゃん!!よーし、今後は多用するぞ!!」

mergeとrebaseの違いについては記事が世の中に溢れかえってるので割愛します。
ただ、
「コレをrebaseしたらコンフリクト地獄で終わるからmergeしよう」
「ここはmergeするとコミットがわけわからないことになるからリベースしよう」
といった使い分けは必要ですし、

  • mergeは動きが分かりやすいがコミット履歴は散らかりやすくなる
  • rebaseはコミット履歴を綺麗にしやすいが調子こくとやらかしやすい

といった特徴もあるので一概に断言できません。
そこを勘違いした月君は・・・

コミット履歴をまとめる

A先輩「月君の作業コミット、多すぎてマージしたときに散らかってしまうから不要な部分は整理するようにしてね。」
月君「はい、わかりました。(わかってない)」

スクリーンショット 2018-05-28 18.34.52.png

月君はとりあえずコミットをそのままpushしてプルリクエストを出していたようです。
これではコミット履歴が乱雑になる原因になってしまいます。

月君「ググったぞ!!rebase -iだ!!」

$ (moon_dev2) git rebase -i HEAD~5

HEAD~5はHEADから5つのコミットを対象とする。(HEAD~~~~~と同義)
2行目からのpicks(squashの略)にして保存。
余計なコミットをsquashでまとめ、「一旦コミット」というコミットログを変更します。(vi系は:wq)

スクリーンショット 2018-05-28 18.54.10.png
参考:git rebaseでsquashした場合とfixupした場合の違い

スクリーンショット 2018-05-28 18.54.36.png

コミットログを変更したら保存

スクリーンショット 2018-05-28 18.59.40.png

月君push -fだ!!!」

$ (moon_dev2) git push -f origin moon_dev2

スクリーンショット 2018-05-28 19.00.33.png

コミットがまとまりました。


まとめるコミット数を間違えた場合

$ (moon_dev2) git rebase -i HEAD~6

(略)

スクリーンショット 2018-05-28 19.04.52.png

月君はこの間違いに気づかず...

月君push -fだ!!!!」

スクリーンショット 2018-05-28 19.07.21.png

月君「!?」

こうなると、developのHEADより1つ前のコミットで分岐された過去になってしまうので、
mergeしようとするとコンフリクトを起こします。
(今回はdevelopのHEADとmoon_devのHEADで修正されているファイルが同じな為)


月君のようによく考えずrebaseしたりpush -fを多用するとその時は来てしまいます。

後編「月君のやらかし事例とその対処」

9
3
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
9
3