質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.63%

gitのブランチの異なるコミットを整理したい。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 138

helo

score 18

前提・実現したいこと

Ruby on Railsチュートリアルを進めているのですが、
git merge が何度となく失敗し、マージできないファイルが数個出てしまいます。
全く前に進めなくて困っています。このような場合はどう対処すれば良いのでしょうか。詳しい方いらっしゃいましたらアドバイス頂けないでしょうか。
よろしくお願いします。

発生している問題・エラーメッセージ

$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 1 and 1 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

nothing to commit, working tree clean

該当のソースコード

ここに言語名を入力

試したこと

git reset --hard
等行いましたが、改善にならず、git clean -f でコミットしたものを消したのですが、ブランチマスター上にブランチとオリジン/マスターが分岐しどちらにも違うコミットが残ってしまっているのが問題なのではと思っています。

補足情報(FW/ツールのバージョン

Windows 10 

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • helo

    2020/02/13 23:44

    お送りいたします。よろしくお願いします。

    $ git branch -avv * filling-in-layout b3c1ea4 Add a full_title helper
    filling-in-leyout d80cf26 Finish layout and routes
    filling-in-re-layout 6b32b95 Finish layout and routes
    master b3c1ea4 [origin/master: ahead 1, behind 1] Add a full_title helper
    rails-flavored-ruby f8e15a5 Add a full_title helper
    static-pages 592d781 [origin/static-pages: ahead 1] Finish static pages
    remotes/heroku/master f8e15a5 Add a full_title helper
    remotes/origin/master f8e15a5 Add a full_title helper
    remotes/origin/static-pages 82cb5b9 Add a Static Pages controller

    キャンセル

  • hoshi-takanori

    2020/02/14 00:01

    あれ、新しいブランチがありますね。のんびり書いてる場合じゃなかった。(あせ)

    キャンセル

  • helo

    2020/02/14 23:10

    hoshi-takanori様
    ありがとうございます。
    この新しいブランチは、3回目のコーディングに着手しかかっていたものです。
    問題がきちんと把握できてない中、やり直したら上手く行かないか?と思ってやってしまったものです。
    情けないです・・・。
    回答を確認させていただきました。大変丁寧に記述頂いていてびっくり致しました。もの凄く分かり易すいので大変ありがたいです。自分自身まだgitをきちんと理解できていないのが良く分かりました。
    良い勉強をさせていただきました。ありがとうございます。
    兎に角、これでやってみます!

    キャンセル

回答 1

checkベストアンサー

+1

現在のブランチの状況は

$ git log --graph --oneline --all
* 6b32b95 (filling-in-re-layout) Finish layout and routes
* b3c1ea4 (HEAD -> master) Add a full_title helper
| * d80cf26 (filling-in-leyout) Finish layout and routes
| * f8e15a5 (origin/master, heroku/master, rails-flavored-ruby) Add a full_title helper
|/
* d7a405c Complete advanced setup
* 592d781 (static-pages) Finish static pages
* 82cb5b9 (origin/static-pages) Add a Static Pages controller
* 81963a7 Add hello
* 50f4e2e Improve the README
* 293096f Initialize repository

ということで、d7a405c から二つに分かれて同じような作業を行ったと理解しました。

git の merge というのは、二つのブランチで別々の作業(例えば、片方はバグ修正、もう片方は新機能の追加)を行なったような場合に、両方の変更を取り込むために行うものです。別々の作業といっても同じ箇所に変更を加えてしまう場合があり(例えば、バグ修正のために修正した関数に新機能を追加したなど)、merge の際にコンフリクトが発生するのはよくあることなので、世間に出回っているコンフリクト解消のための記事にはそういう前提で書かれているものが多いと思います。

一方、両方のブランチで同じような変更を行った場合、変更のほとんどがコンフリクトしてしまいます。それらを merge することももちろん可能ですが、同じような変更をわざわざ merge する意味はあまりないと思います。そういう場合は、変更内容を確認した上で、片方のブランチを捨てる(不採用にする)という手もあると思います。

さて、現在のブランチの状況はこのように二つの枝分かれがあります。

              +--- f8e15a5 (origin/master) --- d80cf26 (filling-in-leyout)
             /
--- d7a405c +
             \
              +--- b3c1ea4 (master) --- 6b32b95 (filling-in-re-layout)

それぞれのコミットにおける変更内容を確認しましょう。
(f8e15a5 などの代わりに origin/master などで指定することもできます。)

$ git diff d7a405c..f8e15a5

(共通の親から f8e15a5 (origin/master) への変更内容)

$ git diff f8e15a5..d80cf26

(f8e15a5 (origin/master) から d80cf26 (filling-in-leyout) への変更内容)

$ git diff d7a405c..b3c1ea4

(共通の親から b3c1ea4 (master, HEAD) への変更内容)

$ git diff b3c1ea4..6b32b95
b3c1ea4 (master) から 6b32b95 (filling-in-re-layout) への変更内容)

diff の見方ですが、行の先頭に - がついて赤く表示された行が削除または変更された行、+ がついて緑で表示された行が追加または変更後の行になります。

また、二つのブランチの違いを表示するにはこうします。

$ git diff f8e15a5..b3c1ea4

(f8e15a5 (origin/master) と b3c1ea4 (HEAD -> master) の違い)

$ git diff f8e15a5..d80cf26

(d80cf26 (filling-in-leyout) と 6b32b95 (filling-in-re-layout) の違い)

これらがほとんど同じなら、どちらの枝分かれを採用しても良いと思われます。

ここで、現在の master があるブランチ (b3c1ea4, 6b32b95) を不採用にして、origin/master 側 (f8e15a5, d80cf26) を採用するとしましょう。例えば以下のようにします。(git は同じ結果になる方法が複数あるので、これは一例です。)

$ git checkout master

(master ブランチを操作するので、master ブランチに切り替えます。)

$ git reset --hard HEAD^

(master ブランチの現在位置を b3c1ea4 から d7a405c に移動します。)
(なお、--hard オプションは作業ディレクトに内容も d7a405c のものに変更するという意味です。)

$ git merge --ff-only origin/master

(master ブランチに origin/master の変更内容を取り込みます。)
(master ブランチは origin/master の祖先なので、master ブランチが origin/master の位置に移動するはず。)

$ git merge --ff-only filling-in-re-layout

(master ブランチに filling-in-re-layout の変更内容を取り込みます。)
(master ブランチは filling-in-re-layout の祖先なので、master ブランチが filling-in-re-layout の位置に移動するはず。)

git merge は枝分かれした二つのブランチの変更内容をマージするのが本来の使い方ですが、枝分かれしてない場合に先行しているブランチに追いつくためにも使えます。その際、間違って新たにマージコミットを作らないように --ff-only オプションをつけています。
(すでに状況が変わってるようですが、基本的な考え方がわかれば応用できると思います。)

別の方法としては、master ブランチを一旦消して新たな位置に作り直したり、master ブランチを別の名前にして、別のブランチの名前を master に変更こともできますが、危険な香りがする(実際はそれほど危険ではありませんが)ので今回はやめておきます。


また、git branch でブランチを一覧表示できます。自分はよく -avv オプションをつけます。

$ git branch -avv
* filling-in-layout           b3c1ea4 Add a full_title helper
  filling-in-leyout           d80cf26 Finish layout and routes
  filling-in-re-layout        6b32b95 Finish layout and routes
  master                      b3c1ea4 [origin/master: ahead 1, behind 1] Add a full_title helper
  rails-flavored-ruby         f8e15a5 Add a full_title helper
  static-pages                592d781 [origin/static-pages: ahead 1] Finish static pages
  remotes/heroku/master       f8e15a5 Add a full_title helper
  remotes/origin/master       f8e15a5 Add a full_title helper
  remotes/origin/static-pages 82cb5b9 Add a Static Pages controller

remotes/ で始まるブランチはリモートブランチ、それ以外はローカルブランチです。自分が今いるブランチは * がついてます。また、[origin/master: ahead 1, behind 1] はリモートブランチに対応したブランチ、ahead はローカルが先行、behind はリモートが先行していることを意味します。ここで、ahead であれば git push、behind であれば git pull を行えば同期できますが、問題は両方ある場合で、まず git pull してリモートの変更内容を取り込んで(コンフリクトした場合はそれを解消して)から git push することになります。

ブランチは消さない限り残ってますので、不採用にしたブランチでもいつでも内容を確認できますし、チェックアウトして作業を再開することもできます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/02/15 10:17

    hoshi-takanori様
    ご回答ありがとうございました。記述頂きました方法でやってみました。
    一先ず、filling-in-re-layoutのほうになってしまったですが、マージは成功しました。ありがとうございます。
    そのあとpushすると以下の表記が出てまた立ち往生してしまいました。。。
    $ git push
    To bitbucket.org:satoshi_toto/sample_app.git
    ! [rejected] master -> master (non-fast-forward)
    error: failed to push some refs to 'git@bitbucket.org:satoshi_toto/sample_app.git'
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Integrate the remote changes (e.g.
    hint: 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    その後、pullをしたら、以下の表記になりましたので

    Auto-merging test/controllers/static_pages_controller_test.rb
    CONFLICT (content): Merge conflict in test/controllers/static_pages_controller_test.rb
    Auto-merging app/views/static_pages/home.html.erb
    CONFLICT (content): Merge conflict in app/views/static_pages/home.html.erb
    Auto-merging app/views/layouts/application.html.erb
    CONFLICT (content): Merge conflict in app/views/layouts/application.html.erb
    Automatic merge failed; fix conflicts and then commit the result.

    コンフリクトを起こしているファイルをツリー上でrmしたのですが
    エラーが出てしまいました。
    $ git pull
    error: Pulling is not possible because you have unmerged files.
    hint: Fix them up in the work tree, and then use 'git add/rm <file>'
    hint: as appropriate to mark resolution and make a commit.
    fatal: Exiting because of an unresolved conflict.

    アドバイス頂いたように進んでいるのかも自分自身定かでは無く、行き詰まってしまいました。マージ後で何か間違ったコマンドをやってしまったいるでしょうか・・・。

    キャンセル

  • 2020/02/15 11:55

    hoshi-takanori様
    その後、コンフリクトファイルを何度もaddしてmergeしていき都度、vimで悪戦苦闘しましたが、何とか無事にgit push → herokuへもpushできました。本当にありがとうございました。
    今後は、mergeの際のコンフリクトも恐れないでやって行けそうです。
    本当に、ご丁寧な解説とアドバイスをいただきまして大変感謝いたします。
    またチュートリアルを頑張って参ります。
    それでは失礼いたします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る