19

メインプロジェクト内のサブプロジェクトを管理するために、git-subtree拡張機能(https://github.com/apenwarr/git-subtree )を使用しています。サブプロジェクトに加えられた変更をメインプロジェクトから分割しようとすると失敗するという事実以外は、私が望んでいることを正確に実行しています。

たとえば、以前に私がやった

git subtree add -P Some/Sub/Dir --squash git@gitserver:lib.git master

メインプロジェクトのSome/Sub/Dirにライブラリコードを取り込みます。ここのすべてがうまくいったので、私は変更を中央のメインプロジェクトの裸のgitリポジトリにプッシュしました。次に、Some / Sub / Dirでローカルバージョンのライブラリに変更を加え、コミットしてから分割して、lib.gitリポジトリにプッシュすることにしました。

git subtree split -P Some/Sub/Dir -b some_branch

すべてが期待どおりに機能します。リポジトリのローカルコピーはもう必要ありません。削除しました。

中央リポジトリからリポジトリの新しいコピーを複製した後、Some / Sub / Dirのlibにいくつかの変更を加え、それらの変更を分割してlib.gitリポジトリにプッシュバックすることにしました。以前と同じサブツリー分割コマンドを使用しようとしましたが、今回は次の出力になります。

1/      3 (0)
2/      3 (1)
3/      3 (1)
fatal: bad object d76a03f0ec7e20724bcfa253e6a03683211a7bb1

d76a03f0ec7e20724bcfa253e6a03683211a7bb1は、サブツリーを追加したときのものです。

commit 43b3eb7d69d5eb64241eddb12e5bd74fd0215083
Author: Ian Bond <ibond@onezero.com>
Date:   Fri Apr 22 15:06:50 2011 -0400

    Squashed 'Subtree/librepoLib/' content from commit d76a03f

    git-subtree-dir: Subtree/librepoLib
    git-subtree-split: d76a03f0ec7e20724bcfa253e6a03683211a7bb1

これは実際にはlib.gitリポジトリのコミットを指します。


私がつなぎ合わせることができたのは(そして私はgit noobなので、間違っているか、何かを見落としているか、ここで間違った用語を使用している可能性があります)、「git subtree add --squash」は、リモートのlib.gitレポジトリを現在のレポジトリに押し込み、別のコミットに押しつぶしてから、そのコミットを作業ブランチに追加します。lib.gitのコミット履歴は現在のリポジトリに残りますが、スカッシュコミットのテキスト以外では実際に参照されていないため、コミットがぶら下がっています。それらのぶら下がりコミットが残っている限り、git-subtreeはそれらを使用して分割を実行できますが、プッシュまたはプルにはぶら下がりオブジェクトが含まれていないため(または、gcを実行してぶら下がりオブジェクトを完全に削除した場合)、それらのぶら下がりコミットは失われ、 git-subtreeには、分割を実行するために必要な情報がありません。

私が抱えていた問題を完全に再現するスクリプトを追加しました。


私の質問は次のとおりです。

1)元のリポジトリにマージしたいサブツリーがあり、それらをリンクする履歴がなくなったという既存の状況を処理するにはどうすればよいですか。私の現在の考えは、次のようなことをすることです。

git subtree split -P Some/Sub/Dir 43b3eb7^.. --ignore-joins -b splitBranch

'git subtree add'以降のすべての履歴を分割し、元のリポジトリにマージして戻します(ありがたいことに、追加以降、変更はありません)。これが最善の方法ですか?マージを実行する方法に関する推奨事項はありますか?

2) git-subtreeを期待どおりに機能させるためにできることはありますか?'git subtree add'の--squashパラメーターを省略すると、すべてが機能すると思いますが、それにより、無関係な履歴の束がリポジトリに挿入されます。必要なコミットを維持する方法はありますか(できれば、ライブラリの履歴全体を維持することなく)?

4

2 に答える 2

15
于 2011-04-23T09:18:05.027 に答える
1

@Chris Johnsen's answer is very right, it explains why spliting works in the clone not a pull situation.

For the work around provided in the question and explained in footnote 2 of @Chris Johnsen's answer, I can confirm that git subtree split -P Some/Sub/Dir -b splitBranch --ignore-joins and git subtree split -P Some/Sub/Dir -b splitBranch 43b3eb7.. are acturally produced the same commit and same branch which can reflect the modifications done in the local repo, but can not be pushed to the original repoLib repo, because they don't have a common accesstor, even though git diff shows d76a03f0ec7e2 and 43b3eb7d69d are the same.

So, in order to get subtree push working in a pull situation, the original repoLib remote repo must be added and fetched to get d76a03f0ec7e2 exsited to produce a branch that have a common accesstor with the original repoLib.

The original reproduce script could not run smoothly under linux, here is a new one: http://pastebin.com/3NAQKEz9

于 2012-03-08T15:41:47.107 に答える