4

私はgit 1.8.2でサブツリーのマージを学び始めています。メイン プロジェクトに移行するサード パーティのリポジトリへの変更をテストする簡単な例を作成しました。

私は6.7 Git Tools - Subtree Mergingの例に従っています。

「サブ」プロジェクトは、「メイン」プロジェクトのサブディレクトリとして含まれています。

「サブ」プロジェクトに変更を加えた後、その変更を「メイン」プロジェクトにマージしようとすると、git が競合を報告します。

テストのまとめ

  1. プロジェクト 'main' および 'sub' (ラックではなくサブ) のリポジトリを作成しました
  2. sub_remote という名前のリモートを、サブを参照するメインに追加します
  3. sub_branch を使用して sub_remote を追跡する
  4. 「サブ」プロジェクトのファイルの 1 行を変更してコミットする
  5. sub から main/sub_branch に変更をプルします
  6. main/sub_branch を main/master にマージします。

マージは競合で失敗します。Merge は、変更された行のどのバージョンを保持するかについて混乱しています。

<<<<<<< HEAD
main
=======
main upstream change
>>>>>>> sub_branch
main.git
sub
sub.git
tm

完全なテスト スクリプト

#!/bin/sh

# initialize empty repos
for i in main sub
do
  rm -rf $i{,.git}
  mkdir $i.git
  cd $i.git;
  git --bare init;
  cd ..;
  git clone $i.git
  cd $i
  echo $i > readme.md
  git add readme.md
  git commit -a -m "added readme.md"
  git push origin master
  cd ..
done

# add data to sub
ls > sub/data
cd sub
git add data
git commit -m "Added data"
git push origin master
cd ..

# add sub as a sub-tree in main
cd main
git remote add sub_remote ../sub.git
git fetch sub_remote
git checkout -b sub_branch sub_remote/master
git checkout master
git read-tree --prefix=sub/ -u sub_branch
git commit -m "Added sub"
git push origin master
cd ..

# make change to sub
cd sub
sed -i -e 's/main$/main upstream change/' data
git commit -a -m "upstream change made to data"
git push origin master
cd ..

# merge sub change to main
cd main
git checkout sub_branch
git pull

#merge sub_branch changes into master
git checkout master
git merge -s subtree sub_branch
cat sub/data
4

2 に答える 2

6

read-treeこの場合、現在のツリーのディレクトリに別のツリーの内容を追加するだけです。このコンテンツは、通常のファイルとディレクトリが作成および追加されるのと同じように追加され、履歴は引き継がれません。これらのファイルはすべて、自分で作成したかのように扱われます。

マージしようとすると、sub_branch の履歴によってファイルが作成されdata、ターゲット ディレクトリにもdataユーザーが作成した別のファイルが含まれているため、プロセスは失敗します。

使用しているページには、サブツリーを適切に機能させるための非常に重要な手順が欠けているため、実際に更新をプルできるようになっています。

適切な例は、次の両方のページで確認できます: https://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html https://help.github.com/ article/working-with-subtree-merge

あなたの場合に欠けているのは、サブツリーを作成するときに履歴を適切にリンクすることです:

# create the merge record but not change anything in your tree yet
git merge -s ours --no-commit sub_branch
# bring the changes and place them in the proper subdirectory
git read-tree --prefix=sub/ -u sub_branch

この後、mainリポジトリにはリポジトリの履歴が含まれsubます。失敗していたマージの呼び出しが適切に機能するようになりました。呼び出すgit log --graphと、さまざまなコミットがどのようにマージされているかを確認できます。

于 2013-04-05T19:02:10.137 に答える
0

問題は、Git 1.8.2.2 (2013 年 3 月) が、git merge -s subtree. まだ問題があるTim Swastが言及した
Subtree Merging セクションは、Git 2.19 (Q3 2018) でより適切に機能するはずです。

" " の自動ツリー マッチングはgit merge -s subtree5 年前に機能しなくなり、それ以来誰も気づいていませんでしたが、現在は修正されています。

Jeff King ( )によるcommit 2ec4150 (2018 年 8 月 2 日)を参照してください。 助っ人:ルネ・シャルフ ( ) . ( 2018 年 8 月 17 日コミット 60858f3Junio C Hamanoによってマージされました)peff
rscharfe
gitster

score_trees(): エントリが欠落しているツリーの反復処理を修正

ではscore_trees()、ソートされた 2 つのツリーを調べて、欠落しているエントリや内容が異なるエントリを見つけます。
したがって、これらのエントリを持つ 2 つのツリーがあるとします。

one   two
---   ---
a     a
b     c
c     d

ループが次のことを期待します。

  • 「a」と「a」を比較する
  • 「b」と「c」を比較します。これらはソートされたリストであるため、2 番目のツリーには "b" がないことがわかります。
  • "c" と "c" を比較する
  • 「d」をリストの終わりと比較します。最初のツリーには「d」がないことがわかっています

そして、d8febde ( match-trees: simple score_trees()using tree_entry()、2013-03-24、Git 1.8.2.2) の前は機能していました。
しかし、そのコミットの後、片側のみのエントリを処理した場合でも、ループの反復ごとにツリー ポインタを誤ってインクリメントします
その結果、次のようになります。

  • 「a」と「a」を比較する
  • 「b」と「c」を比較します。「b」がないことはわかっていますが、両方のツリー ポインターをインクリメントします。この時点で同期が取れておらず、それ以降の比較はすべて間違っています
  • "c" と "d" を比較して、2 番目のツリーには "c" がないと誤って主張する
  • 最初のツリーに「d」がないことに誤って気付かずに、ループを終了します

したがって、d8febdeupdate_tree_entry()の主張とは反対に、ツリー ポインタの前進はエントリの比較に依存するため、実際には を手動で使用する必要があります。

つまりtree_entry()、ポインターを自動的に進めるため、各エントリへのアクセスを停止する必要があります。
その代わり:

  • tree_desc.size調べるものが残っているかどうかを知るために直接使用します(これは内部tree_entry()で行っていたことです)
  • e1" " と " "に余分な構造体を代入するのではなく、" " フィールドに直接e2アクセスできます。entrytree_desc
于 2018-08-19T14:06:58.233 に答える