フライさん(loxygen)です。限界開発鯖でのだのだ言っています。フライさんにおまかせなのだ!
説明はあまり得意ではありません。
※この記事は茨城高専生向けに書かれたものです。
お説明
前回使用したリポジトリを引っ張ってきて、そこでGit Bashを開いておいてください。
現在のコミット履歴は以下のようになっています。
コンフリクト
hello.txt
がこれまでどのように編集されてきたかを見てみましょう。
add-new-func
ブランチとadd-new-func-2
ブランチの編集場所がまるっきりかぶっています。
これでは**add-new-func
ブランチとadd-new-func-2
ブランチ両方の内容を取り入れることができません**。
だからと言ってどちらかの変更を消し飛ばすのも人間性がありません。
通常Gitはgit merge 〇〇
コマンドを打てば自動でマージしてくれますが、こうなってしまうとどうすれば良いのかわかりません。するとGitは「コンフリクト」を宣言します。
コンフリクトになると、Gitの代わりに開発者自らの手で変更内容をマージする作業が必要になります。
だから開発者はコンフリクトを忌み嫌うわけですね。
確認作業
前回、「マージする前に確認作業をするとお作法がいいよ」という話をしました。
どうして確認作業が必要なんですか
確認作業の説明の前に、存在意義を説明させてください。
ちょっとこの図をご覧ください。
さっき上に出した図の簡略版です。
前回のお練習の中でadd-new-func-2
ブランチを作りましたね。
同じ要領でマージしようとしてみました。
すると、先程の理由で**コンフリクトします。**コミット履歴はこのようになります:
この後手動でマージ作業を行うわけですが、その作業を行うブランチは先程チェックアウトした**master
ブランチです。
前回**master
ブランチは品質が保証される**ということを記述しましたが、そんなmaster
ブランチで作業をするのは極めておっかないことはわかりますよね。
マージ作業に失敗したらバグがあったり、最悪の場合全く動かない状態のものがmaster
ブランチにコミットされてしまいます**。ああ、怖い怖い!
確認作業
そこで、master
ブランチにチェックアウトした状態でのコンフリクトを防ぐために、
事前にadd-new-func-2
ブランチでコンフリクトを発生させるということを行います。
これこそが確認作業です。便宜上確認作業と読んでいますが、正式なお名前はたぶんないです。
こういうことです:
master
ブランチからadd-new-func-2
に、逆方向にマージしてからmaster
にマージしています。
こうすることでマージ作業をadd-new-func-2
ブランチで行ってからmaster
にマージすることができます。
master
ブランチじゃないところでマージ作業ができるので、気が楽ですし、何より安全です。
確認作業を行った上でマージしてみる
習うより慣れろ、と昔偉い人は言いました。実際にやってみましょう。
逆マージする
まずはadd-new-func-2
にmaster
をマージするんでしたね。
マージの方法は前回説明しました。やってみましょう。
$ git checkout add-new-func-2
Switched to branch 'add-new-func-2'.
$ git merge master
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt
Automatic merge failed; fix conflicts and then commit the result.
…ん?failed
ですって?
はい。先程の理由でコンフリクトしました。
git status
も見てみましょう。
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: hello.txt
no changes added to commit (use "git add" and/or "git commit -a")
You have unmerged paths
…まだマージしきれてないやつがあるで!
と言われていますね。
ファイルには何が起こっている?
hello.txt
の中身を見てみましょう。
中身はcat
コマンドで見れます。もちろん任意のテキストエディタで見ても大丈夫です。
$ cat hello.txt
上のコマンドを叩く、またはテキストファイルを任意のエディタで見ると以下のようになっています:
<<<<<<< HEAD
I am the kindest person.
=======
I am the greatest people.
>>>>>>> add-new-func-2
世界が急に混沌に包まれてしまいました。落ち着いて読み解いて行きましょう。と言っても簡単です。
これだけです。現在のブランチ(マージ先)の状態とマージ元の変更内容が一緒に書いてあるだけです。
解消する
解消方法は至って簡単で、2つのブランチの変更内容をいい感じにフュージョンしてやればOKです。1
今回の場合は、I am the kindest human.
とI am the greatest people.
をいい感じにフュージョンしてやればいいわけです。
hello.txt
をご自由に変更してみてください。
おヒント
筆者の場合は…
-
kindest
とgreatest
については、2つの特徴を両方取り入れて、I am the kindest and greatest ***.
にしたい -
human
とpeople
という単語は不適切2なので、person
に修正したい
と考えました。
というわけで、筆者であれば以下のように修正します。
I am the kindest and greatest person.
いい感じにフュージョンできたら、「<<<<<<< HEAD
」から「>>>>>>> add-new-func-2
」は消してください。
コンフリクト解消
全てのコンフリクトが解消できたら(今回の場合は一箇所だけなのでこれで終わりです)、いつものようにAddしてCommitしましょう。
$ git add --all
git status
も見ておきましょう。
$ git status
On branch add-new-func-2
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: hello.txt
All conflicts fixed but you are still merging
…「コンフリクトは全部直ったけどまだマージ作業中やで!」と言われています。まだコミットしてないからですね。コミットをしましょう。
$ git commit -m "Resolved conflict between master and add-new-func-2"
[add-new-func-2 ef01234] Resolved conflict between master and add-new-func-2
これでコンフリクトが解消され、add-new-func-2
上でコンフリクトの修正に成功しました。
コミット履歴はこうなっています:
masterにマージする
これでmaster
ブランチとのコンフリクトが起きない状態になったので、心に余裕を持ってマージすることができます。ちゃちゃっとやってしまいましょう。
$ git checkout master
Switched to branch 'master'
Updating 38f1b56..03eafb0
Fast-forward
hello.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
一応hello.txt
の中身も見てみましょう。例のごとくcat
コマンドを使用しますが、お好みのエディタで確認しても大丈夫です。
$ cat hello.txt
I am the kindest and greatest person.
先程修正した内容が正常にmaster
ブランチに反映されていますね。
コミット履歴はこうなりました:
これでようやくコンフリクトした状態からのマージに成功しました。お疲れ様でした。
マージ作業を取りやめたい場合
なにか事情があって途中でマージ作業をキャンセルしたくなったとします。その時は以下のコマンドを入力してください:
$ git merge --abort
「コンフリクト起こらんやろ!」って場合
例えば小さい変更だったり、他の人が全くいじらなかったところを変更したりした場合などで、コンフリクトする確率は低いと判断できる場合があります。
その場合はちょっとお行儀悪いですが、確認作業を踏まずにmasterにマージして問題ないでしょう。
コンフリクトしてしまった場合は、そこで直さずにgit merge --abort
を実行してから、マージする元のブランチにいって確認作業を踏むと世界が平和になります。
以下に**「コンフリクト起こらんやろ!と信じてmaster
ブランチに直接マージしようとしたものの、コンフリクトしてしまい元のブランチで確認作業を行ったときの動き」**を記しておきます。
(なお、すでにadd-new-func-2
はマージしてしまったので以下のコマンドは動きません)
$ git checkout master
Switched to branch 'master'
$ git merge add-new-func-2
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt
Automatic merge failed; fix conflicts and then commit the result.
$ git merge --abort # 一旦マージ作業をやめる
$ git checkout add-new-func-2
Switched to branch 'add-new-func-2'
# 以下確認作業を行う
おまとめ
- 別々のブランチで同じファイルの同じ場所を編集するとコンフリクトが起こる
- 以下の「確認作業」を踏むのが好ましい
- 1.
master
ブランチを作業中のブランチにマージする -
- コンフリクトが発生したら以下の手段を踏む:
-
-
>>>>>>> 〇〇
と<<<<<<< ⬜⬜
の間をいい感じにフュージョンする
-
-
- 全部終わったら
git add --all
してgit commit
- 全部終わったら
-
-
master
ブランチにチェックアウトする
-
-
- マージする
- 1.
- 強制ではないので、「多分コンフリクト起こらんやろ〜」と判断できる場合は飛ばしても良い
これでブランチについてはひとまず終了です。ここまで本当にお疲れ様でした!
おリンク
第1回 インストール編
第2回 設定編
第3回 実際に使ってみよう-基本技能編
第4回 ブランチ(平行世界)編-1
第5回 いまここ
第6回 GitHub入門編
第7回 fetch/pull編
第8回 issue/Pull Request編