24

それで、私はより大きな(クローズドソース)プロジェクトを持っており、このプロジェクトのコンテキストで、他の場所でも役立つ可能性のあるライブラリを作成したと思います.

私は今、ライブラリを独自のプロジェクトに分割したいと考えています。これは、github などでオープン ソースとして使用できます。もちろん、ライブラリ (およびそこにあるその履歴) には、プロジェクトの痕跡が含まれていてはなりません。

ここでは git-subtree が解決策のように思えますが、完全には適合しません。

私のディレクトリレイアウトは次のようなものです(Javaプロジェクトであるため):

  • フェンシングゲーム (git workdir)
    • ソース
        • フェンシング_ゲーム
          • トランスポート (私のライブラリ)
            • プロトコル (ライブラリの一部)
            • フェンシング(ライブラリと接続するメイン プロジェクトの一部)
            • クライアント(ライブラリと接続するメイン プロジェクトの一部)
            • サーバー(ライブラリと接続するメイン プロジェクトの一部)
          • クライアント(メイン プロジェクトの一部)
          • サーバー(メイン プロジェクトの一部)
          • ... (メインプロジェクトの一部)
    • その他のファイルとディレクトリ (ビルド システム、Web サイトなど - メイン プロジェクトの一部)

分割後、ライブラリのディレクトリ レイアウトを次のようにします (太字のディレクトリにあるすべてのファイルを含む)。

  • my-library (名前は未定)
    • ソース
        • フェンシング_ゲーム
          • トランスポート (私のライブラリ)
            • プロトコル (ライブラリの一部)

履歴には、リポジトリのこの部分に関係するメイン プロジェクトの履歴の一部のみが含まれている必要があります。

一目見ただけでわかりましgit-subtree split --prefix=src/de/fencing_ame/transportたが、これは

  1. transport(コンパイルされない) に根ざしたツリーを教えてください。
  2. transport/clienttransport/serverおよびtransport/fencingディレクトリを含めます。

最初の点は受信側で使用することで軽減できますがgit subtree add --prefix=src/de/fencing_ame/transport <commit>、git-subtree がこれらのサブディレクトリのエクスポートに対してもあまり効果がないと思います。(アイデアは、ここで完全なツリーを共有できるようにすることです)。

ここを使わないといけないのgit filter-branch

分割後、 git-subtree または git-submodule を使用して、メイン プロジェクトのライブラリを現在の場所ではなく別のサブディレクトリにインポートできるようにしたいと考えています。レイアウトはこんな感じ

  • フェンシングゲーム (git workdir)
    • ソース
        • フェンシング_ゲーム
          • トランスポート (空)
            • フェンシング(ライブラリと接続するメイン プロジェクトの一部)
            • クライアント(ライブラリと接続するメイン プロジェクトの一部)
            • サーバー(ライブラリと接続するメイン プロジェクトの一部)
          • クライアント(メイン プロジェクトの一部)
          • サーバー(メイン プロジェクトの一部)
          • ... (メインプロジェクトの一部)
    • マイライブラリ
      • ソース
          • フェンシング_ゲーム
            • トランスポート (私のライブラリ)
              • プロトコル (ライブラリの一部)
    • その他のファイルとディレクトリ (ビルド システム、Web サイトなど - メイン プロジェクトの一部)
これを行うための最も痛みのない方法は何ですか? この目的のために、git-subtree と git-filter-branch 以外のツールはありますか?

4

5 に答える 5

3

私はあなたがやるべきいくつかの本当の洞窟探検を持っていると思います. 「プロトコル」だけを分割したい場合は、「git subtree split ...」または「git filter-branch ...」でそれを行うことができます。

git filter-branch --subdirectory-filter fencing-game/src/de/fencing_game/transport/protocol -- --all

しかし、トランスポート/プロトコルだけでなくトランスポートにもファイルがある場合、それは毛むくじゃらになり始めます。

私が行っていたプロジェクトのために、これを行うためのカスタムツールをいくつか書きました。それらはどこにも公開されていませんが、reposurgeonで同様のことができます。

于 2011-09-20T19:25:52.190 に答える
3

親プロジェクトのファイルが混在するサブツリーを分割する

これは一般的な要求のようですが、このようにフォルダーが混在している場合、簡単な答えはないと思います。

他のフォルダーと混在するライブラリを分割するために私が提案する一般的な方法は次のとおりです。

  1. ライブラリの新しいルートでブランチを作成します。

    git subtree split -P src/de/fencing_game -b temp-br
    git checkout temp-br
    
    # -or-, if you really want to keep the full path:
    
    git checkout -b temp-br
    cd src/de/fencing_game
    
  2. 次に、何かを使用して履歴を書き換え、ライブラリの一部ではない部分を削除します。私はこれの専門家ではありませんが、実験することができ、次のようなものが機能することがわかりました。

    git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch client server otherstuff' HEAD
    
    # also clear out stuff from the sub dir
    cd transport 
    git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch fencing client server' HEAD
    

    注: 連続するコマンド間で filter-branch によって作成されたバックアップを削除する必要がある場合があります。

    git update-ref -d refs/original/refs/heads/temp-br
    
  3. 最後に、ライブラリの新しいレポを作成し、残っているものをすべて取り込みます。

    cd <new-lib-repo>
    git init
    git pull <original-repo> temp-br
    

/transport/protocol親プロジェクトの完全なパスではなく、最終的なライブラリ パスをより似たものにすることをお勧めします。

于 2014-03-07T19:35:50.377 に答える
2

ここでの問題は、ライブラリの一部とそうでないものを適切に分離できないことです。ソリューションをリファクタリングしてから、ライブラリをサブモジュールとして含めることを強くお勧めします。

このライブラリの再利用が他の開発者による同じリポジトリにある場合は、それらの変更を別のブランチで追跡し、追加のリポジトリを気にしないでください。

于 2011-06-19T17:25:40.103 に答える
1

プロジェクトの歴史はあなたの利益のためだけのものですか、それとも github 上の人々の利益のためのものですか?

歴史があなたの利益のためだけであれば、グラフトを使用する簡単な方法があります. 基本的には、github 用のまったく新しいリポジトリを作成し、独自のコードをすべて削除するだけです。これで、github にプッシュできるパブリック コードのみを含むオープン ソース リポジトリができました。オープン ソース リポジトリのローカル コピーでは、独自のリポジトリの履歴をオープン ソース リポジトリに移植できます。

このようにすると、あなた (または独自のリポジトリにアクセスできる人) は完全な履歴を見ることができるという利点がありますが、一般の人々は、あなたがオープン ソース化した時点からのコードしか見ることができません。

.git/info/grafts は何のためにあるのですか?

于 2011-06-19T17:23:20.270 に答える
1

私は似たようなことをしましたが、いくつかのディレクトリを暗号化されたパーティション (/secure/tmp/newrepo) 上の完全に別のレポに分割したため、ラップトップ泥棒には利用できませんでした。私はシェル スクリプトを作成し、次のようにしました。 )


#!/bin/sh
# to be used with  e.g:
# git filter-branch --tree-filter '~/bin/tryit /secure/tmp/newrepo personal private' 
# Don't do it on any repository you can't repeatedly do: 
#   rm -rf foo ; git clone /wherever/is/foo 
# when it breaks
SRC=`pwd`
DEST=$1
shift
MSG=/dev/shm/msg.txt
TAR=/dev/shm/tmp.tar
LIST=/dev/shm/list.txt
LOG=/dev/shm/log
DONE=''

echo $GIT_AUTHOR_DATE >> $LOG
git show --raw $GIT_COMMIT > $MSG 

for A in $* 
do 

if [ -d $A ] 
then 
DONE=${DONE}x
tar -cf $TAR $A 
tar -tf $TAR > ${LIST}
cat ${LIST} >> ${LOG}
rm -rf ${A}
cd ${DEST}
tar -xf $TAR
else
echo $A non-existant >> ${LOG}
fi
cd $SRC
done

if [ -z "${DONE}" ]
then
echo Empty >>$LOG
else
cd ${DEST}
unset GIT_INDEX_FILE
unset GIT_DIR
unset GIT_COMMIT
unset GIT_WORK_TREE
touch foo
git add .
git commit -a -F ${MSG}  >> ${LOG}
fi
exit 0

あなたの目的のために、おそらく tar に別の仕様 ( --exclude= など) を設定してから、 cat ${LIST} | を使用することをお勧めします。xargs rm を使用して tar 内のもののみを削除しますが、それを正しく行うのはそれほど難しいことではないと思います。

filter-branch はそれらをソース リポジトリに設定し (必要なものではありません)、sh がスクリプトの最後のコマンドからゼロ以外の終了コードを渡すと終了するため、unset stuff と exit 0 は重要です。

于 2012-01-04T14:41:33.190 に答える