git-subtree プルマージ競合 質問する

git-subtree プルマージ競合 質問する

そこでgit-subtreeを使ってrepoBのさまざまなブランチをrepoAのサブディレクトリに作成しました。

git clone repoA
cd repoA
// some commits to repoA here
git subtree add --prefix=src/dirA repoB branchA

私はrepoAでいくつかのコミットを行いました。

git subtree push --prefix=src/dirA repoB branchA

しばらくして、別の repoC から repoB/branchA に何かをコミットしました。そこでも、git-subtree を使用して branchA が追加されました。

今、私は試しています

git subtree pull --prefix=src/dirA repoB branchA

しかし、明らかな理由もなくマージ競合が発生しています。変更は単純で、まったく競合しません。パッチによって確認されています。

このエラーを修正する方法がわかりません。 同じ/類似の問題を扱っている他の 2 つ または 4 つのスレッドをすでに見つけました。

  1. git-subtree プルの複雑さ
  2. git subtree pull -P whatever <repo> <ref> 常にマージ競合
  3. 中央リポジトリからプルするときに git-subtree の競合が発生する
  4. Git サブツリー マージは、単純な上流の変更をマージするときに競合を報告します。(ただし、これはサブツリーのマージ戦略に関するものです。下記を参照してください)

コミットをリベースしたり編集したりしていないため、これが異なる SHA-1 に関連しているかどうかはわかりません (リンク 1 から 3)。

私の問題はリンク 4 に似ています。git が魔法のように単純なマージに失敗します。ただし、リンク 3 はサブツリー マージ戦略について説明しており、git-subtree については特に説明していないため、これが私の状況にまったく当てはまるかどうかはわかりません。

状況は同じように見えます:

<<<<<<< HEAD
=======
// changes from commit I try to pull from repoB/branchA
>>>>>>> {commit SHA-1 from commit I try to pull from repoB/branchA}

そこで、3ウェイマージウィンドウ(kdiff3)でBASEが明らかに間違っていることに気づきました。しかし、もしそうだとしたら、なぜgitはbase以降のすべての以前のコミットを適用しようとしないのでしょうか?

git log --oneline

マージが失敗した後、マージ/マージを試みる前に、問題のあるコミットの前に重複したコミットがないことがわかります。BASEとして表示されるファイルのバージョンは、最初に発行したときのファイルです。

git subtree add --prefix=src/dirA repoB branchA

repoA 内。

それで何が起こっているのでしょうか? 何らかの理由で git subtree がコミットを見つけられないのに、BASE から HEAD~1 へのコミットを適用しようとせず、実際に不足しているコミット HEAD のみを適用しようとしていることに関係しているようです。

どちらのリポジトリの履歴も台無しにせずにこのエラーを修正するにはどうすればいいでしょうか? なぜ git はこの単純なコミットをプルできず、マージ競合であると判断するのでしょうか?

どのような洞察でも大歓迎です。

ベストアンサー1

さて、私はこれを理解しました。これは 2 つの問題から成っていました。まず、私のツリーは実際には次のようになっていました。

現状

私のツリーには に影響するコミットがありましたが、がすでに移動したsrc/dirAためまだプッシュされていませんでした。repoB/branchA

共通の祖先を探しているため、正しいベースが見つからないことがわかりましたgit subtree pull。そのため、最後に使用したバージョンが使用されました。合併した木々、つまり私がgit subtree add最初に電話したとき。

さて、共通祖先の問題を解決するには、 を実行する必要があります。これは、おざなりなマージを実行し、git が適切なベースを再び見つけられるようにします (つまり、からgit subtree split --rejoinにコミットがプッシュされた後) 。repoArepoB/branchA

しかし、私のケースを見るとわかるように、git subtree split --rejoina の後に a が続くとgit subtree pull問題は解決しません。

Git サブツリーのプル後の壊れた履歴。

プッシュされたかどうかに関係なく、git subtree splitすべてのコミットの合成履歴を作成するため、SHA-1 の合計が異なります。デモ用に合成履歴を独自のブランチに分割しました。src/dirAsplit

git subtree pullは、もちろんその後は成功します。しかし、と合成ツリーの履歴はそれ以降はまったく異なるため、git subtree split --rejoin次は失敗します。git subtree pushrepoB

したがって、問題のあるプッシュされていないコミットの前に戻って、そこから変更を自分のブランチにプルする必要がありました。これは、via がまだ正しいベースを独自に判断できないgit subtree split --rejoinため、依然として必要なため複雑です。git subtree pullgit merge

私の問題に対する最終的な解決策

私が現在行っている方法は解決済み私の問題は、問題のある非プッシュコミットの直前のコミットをチェックアウトしたことにありましたsrc/dirA。その後、git subtree split --rejoinに続いて を実行しましたgit subtree pull。これにより、もちろんメイン ツリーに 2 つのマージが追加されますが、これを 1 つのマージにまとめる方法がわかりませんでした。ソース コードを読んだところ、この問題を簡単に解決できるとは思えません。

が成功した後、ブランチgit subtree pullの残りのコミットを にリベースしました。これで、との共有履歴全体で SHA-1 の合計が一致しました。mastermaster_fixrepoA/master_fixrepoB/branchA

もちろん、これにはリベースの通常の欠点があります。つまり、他の誰かが で作業していた場合master、その履歴は によって台無しになってしまいますgit branch -m master_fix master

おすすめ記事