Qiita内にも数多に存在しているGitの記事。
コマンド然り、奥義や裏ワザもたくさんありますが正直全部覚えなくても開発はできます。
ただ、「機能はわかるけど使い所がわからない」という場合はあるかと思いますので、ある程度厳選してフィクションに沿った状況に応じた使い分けを残します。
※フィクションですよ
設定
- 月君 ... 慣れてくると調子に乗りミスをする常習犯。SouceTree崇拝者。
- A先輩 ... 開発チームメンバーの先輩。デキる意識高い系。
- P上司 ... 二人の上司。通称:レビューの鬼。
前提
- GitFlowを使用している
- Macでvimを使用している
コンフリクト(競合)が発生
月君「ア"ッ!!プルリクだしたのにdevelopブランチとコンフリクトしてる…。A先輩がmergeしたpaisen_A
ブランチが原因か。」
方法1 mergeで対応する
月君「私のmoon_devブランチにdevelopブランチをmergeして発生するコンフリクトを直そう」
月君は「〜動きをチェックするための〜」を「〜動きをチェックしたいがための〜」に変更しましたが、
A先輩は「〜プロジェクト。」を「〜プロジェクトだよ。」にしていたようです。
月君「よし、コンフリクトを解消してmoon_devブランチでマージコミットを作成したぞ。これでOKだ。」
コミット履歴は雑多になりましたが、コンフリクトは解決でき、無事マージされました。
※マージ先のブランチでコンフリクト解消コミットを作成する方法もあります
※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の整合性が取れないというエラーでした。
↑moon_devのリモートブランチとローカルブランチのグラフが全く違います。
こういう時は強制オプション -f
を使用します。(賛否両論有)
$ (moon_dev) git push -f origin moon_dev
moon_dev
リモートブランチが強制的に変更されました。
月君「rebaseの方がコミット履歴綺麗になるじゃん!!よーし、今後は多用するぞ!!」
mergeとrebaseの違いについては記事が世の中に溢れかえってるので割愛します。
ただ、
「コレをrebase
したらコンフリクト地獄で終わるからmergeしよう」
「ここはmerge
するとコミットがわけわからないことになるからリベースしよう」
といった使い分けは必要ですし、
- mergeは動きが分かりやすいがコミット履歴は散らかりやすくなる
- rebaseはコミット履歴を綺麗にしやすいが調子こくとやらかしやすい
といった特徴もあるので一概に断言できません。
そこを勘違いした月君は・・・
コミット履歴をまとめる
A先輩「月君の作業コミット、多すぎてマージしたときに散らかってしまうから不要な部分は整理するようにしてね。」
月君「はい、わかりました。(わかってない)」
月君はとりあえずコミット
をそのままpushしてプルリクエストを出していたようです。
これではコミット履歴が乱雑になる原因になってしまいます。
月君「ググったぞ!!rebase -i
だ!!」
$ (moon_dev2) git rebase -i HEAD~5
HEAD~5
はHEADから5つのコミットを対象とする。(HEAD~~~~~
と同義)
2行目からのpick
をs(squashの略)
にして保存。
余計なコミットをsquashでまとめ、「一旦コミット」というコミットログを変更します。(vi系は:wq
)
参考:git rebaseでsquashした場合とfixupした場合の違い
コミットログを変更したら保存
月君「push -f
だ!!!」
$ (moon_dev2) git push -f origin moon_dev2
コミットがまとまりました。
まとめるコミット数を間違えた場合
$ (moon_dev2) git rebase -i HEAD~6
(略)
月君はこの間違いに気づかず...
月君「push -f
だ!!!!」
月君「!?」
こうなると、develop
のHEADより1つ前のコミットで分岐された過去になってしまうので、
mergeしようとするとコンフリクトを起こします。
(今回はdevelopのHEADとmoon_devのHEADで修正されているファイルが同じな為)
月君のようによく考えずrebase
したりpush -f
を多用するとその時は来てしまいます。