web-dev-qa-db-ja.com

Gitリポジトリトリケのサブディレクトリを複製するにはどうすればいいですか?

私のGitリポジトリには、ルートに2つのサブディレクトリがあります。

/finisht
/static

これが _ svn _ にある場合、/finishtは1か所でチェックアウトされ、/staticは別の場所でチェックアウトされました。

svn co svn+ssh://[email protected]/home/admin/repos/finisht/static static

Gitでこれを行う方法はありますか?

1180
Nick Sergeant

_ edit _ :Git 2.19以降では、この答えでわかるように、これは最終的に可能になります: https://stackoverflow.com/a/52269934/2988

その答えを投票することを検討してください。

注:Git 2.19では、クライアントサイドのサポートのみが実装され、サーバサイドのサポートはまだ不足しているため、ローカルリポジトリのクローンを作成する場合にのみ機能します。大きなGitホスティング会社にも注意してください。 GitHubは、実際にはGitサーバーを使用せず、独自の実装を使用します。そのため、Gitサーバーでサポートが表示されても、それが自動的にGitホストで動作するという意味ではありません。 (OTOHは、Gitサーバーを使用していないので、Gitサーバーに表示される前に、独自の実装でより早く実装することができました。)


いいえ、それはGitでは不可能です。

Gitでこのようなものを実装することはかなりの努力となるでしょう、そしてそれはクライアントサイドのリポジトリの完全性がもはや保証されることができなかったことを意味するでしょう。興味があるなら、gitメーリングリストで "sparse clone"と "sparse fetch"に関する議論を検索してください。

一般に、Gitコミュニティのコンセンサスは、常に独立してチェックアウトされるディレクトリが複数ある場合、これらは実際には2つの異なるプロジェクトであり、2つの異なるリポジトリに存在する必要があるというものです。 Git Submodules を使ってそれらを一緒に接着することができます。

510
Jörg W Mittag

あなたがやろうとしていることは sparse checkout と呼ばれ、その機能はgit 1.7.0(2012年2月)で追加されました。スパースcloneを実行する手順は次のとおりです。

mkdir <repo>
cd <repo>
git init
git remote add -f Origin <url>

これはあなたのリモコンで空のリポジトリを作成し、すべてのオブジェクトを取得しますが、それらをチェックアウトしません。それから:

git config core.sparseCheckout true

今、あなたはあなたが実際にチェックアウトしたいファイル/フォルダを定義する必要があります。これは、それらを.git/info/sparse-checkoutにリストすることによって行われます。例えば:

echo "some/dir/" >> .git/info/sparse-checkout
echo "another/sub/tree" >> .git/info/sparse-checkout

大事なことを言い忘れましたが、リモートからの状態で空のリポジトリを更新します。

git pull Origin master

これで、ファイルシステム上のsome/dirおよびanother/sub/treeのファイルが(チェックアウトされたまま)「チェックアウト」され、他のパスは存在しなくなります。

拡張チュートリアル を見たいと思うかもしれませんし、おそらくスパースチェックアウトの公式の ドキュメントを読むべきです

機能として:

function git_sparse_clone() (
  rurl="$1" localdir="$2" && shift 2

  mkdir -p "$localdir"
  cd "$localdir"

  git init
  git remote add -f Origin "$rurl"

  git config core.sparseCheckout true

  # Loops over remaining args
  for i; do
    echo "$i" >> .git/info/sparse-checkout
  done

  git pull Origin master
)

使用法:

git_sparse_clone "http://github.com/tj/n" "./local/location" "/bin"

これはまだサーバーからリポジトリ全体をダウンロードすることに注意してください - チェックアウトのみサイズが縮小されます。現時点では、単一のディレクトリだけを複製することはできません。しかし、リポジトリの履歴が不要な場合は、最低限のクローンを作成することで少なくとも帯域幅を節約できます。 shallow clone とsparse checkoutを組み合わせる方法については、下記の udondan's answer を参照してください。

1438
Chronial

疎チェックアウト シャロークローン の機能を組み合わせることができます。 浅いクローン は履歴を切り捨て、 疎なチェックアウト はパターンに一致するファイルのみを引き出します。

git init <repo>
cd <repo>
git remote add Origin <url>
git config core.sparsecheckout true
echo "finisht/*" >> .git/info/sparse-checkout
git pull --depth=1 Origin master

これが機能するには最低限git 1.9が必要です。 2.2.0と2.2.2だけで自分でテストしました。

このようにすると、 Push を実行できるようになります。これはgit archiveでは不可能です。

367
udondan

ただダウンロードしたいgithubからのファイル/フォルダである他のユーザのために、単に使用してください:

svn export <repo>/trunk/<folder>

例えば.

svn export https://github.com/lodash/lodash.com/trunk/docs

(はい、それはここにSVNです。どうやら2016年にはまだいくつかのgithubファイルをダウンロードするにはまだSVNが必要です)

提供: GitHubリポジトリから単一のフォルダまたはディレクトリをダウンロードする

重要 - githubのURLを必ず更新し、/tree/master/を '/ trunk /'に置き換えてください。

Bashスクリプトとして:

git-download(){
    folder=${@/tree\/master/trunk}
    folder=${folder/blob\/master/trunk}
    svn export $folder
}

このメソッドはフォルダをダウンロードし、それを複製/チェックアウトしません。変更をリポジトリにプッシュバックすることはできません。一方、スパースチェックアウトやシャローチェックアウトに比べて、ダウンロード数は少なくなります。

113
Anona112

複製元のリポジトリとやり取りする予定がない場合は、完全な git clone を実行し、 git filter-branch --subdirectory-filter を使用してリポジトリを書き換えることができます。このように、少なくとも歴史は保存されるでしょう。

68
hillu

Git 1.7.0には「スパースチェックアウト」があります。 git config manpage の「core.sparseCheckout」、 git read-tree manpage の「Sparse checkout」、および「skip-worktreeビット」を参照してください。 git update-index manページ にあります。

インターフェースはSVNのものほど便利ではありません(例えば、初期のクローン作成時にスパースチェックアウトをする方法はありません)が、より単純なインターフェースを構築するための基本機能は現在利用可能です。

63
Chris Johnsen

これ ははるかに単純に見えます。

git archive --remote=<repo_url> <branch> <path> | tar xvf -
61
ErichBSchulz

Gitだけではサブディレクトリのクローンを作成することはできませんが、いくつかの回避策があります。

フィルター分岐

trunk/public_html/がそのプロジェクトルートであるかのようにリポジトリを書き換えて( filter-branch を使用して)他のすべての履歴を破棄したい場合は、既にチェックアウトしたブランチを試してください:

git filter-branch --subdirectory-filter trunk/public_html -- --all

注:フィルタブランチオプションとリビジョンオプションを分離する--、およびすべてのブランチとタグを書き換える--all。元のコミット時間やマージ情報を含むすべての情報は 保存 になります。このコマンドは.git/info/graftsファイルを尊重し、refs/replace/名前空間を参照します。したがって、移植片または置換refsが定義されている場合は、このコマンドを実行すると永続的になります。

警告!書き換えられた履歴は、すべてのオブジェクトに対して異なるオブジェクト名を持つことになり、元のブランチと収束しません。書き換えたブランチを元のブランチの上に簡単にプッシュして配布することはできません。完全な意味が分からない場合はこのコマンドを使用しないでください。問題を解決するために単純な単一のコミットで十分な場合は、使用しないでください。


スパースチェックアウト

ここに sparse checkout アプローチを使用した簡単な手順があります。これは作業ディレクトリを疎に生成するので、作業ディレクトリ内のどのフォルダまたはファイルがチェックアウトする価値があるかをGitに伝えることができます。

  1. 通常どおりにリポジトリのクローンを作成します(--no-checkoutはオプションです)。

    git clone --no-checkout git@foo/bar.git
    cd bar
    

    リポジトリが既にクローンされている場合は、この手順を飛ばしてもかまいません。

    ヒント:大規模なリポジトリでは、 シャロークローン--depth 1)を検討して最新のリビジョンまたは/および--single-branchのみをチェックアウトします。

  2. sparseCheckoutオプションを有効にします。

    git config core.sparseCheckout true
    
  3. 疎チェックアウト用のフォルダを指定します( 末尾に スペースなし)。

    echo "trunk/public_html/*"> .git/info/sparse-checkout
    

    または.git/info/sparse-checkoutを編集します。

  4. ブランチをチェックアウトします(例:master)。

    git checkout master
    

これで、現在のディレクトリ内のフォルダを選択したはずです。

ディレクトリのレベルが多すぎる場合や、ブランチをフィルタリングする場合は、シンボリックリンクを検討してください。


28
kenorb

私は スクリプトを書いた / GitHub 用。

使用法:

python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>
9
david_adler

これは、単一サブディレクトリの疎チェックアウトの使用例として私が書いたシェルスクリプトです

coSubDir.sh

localRepo=$1
remoteRepo=$2
subDir=$3


# Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder
mkdir ./.$localRepo
cd ./.$localRepo
git init
git remote add -f Origin $remoteRepo
git config core.sparseCheckout true

# Add the subdirectory of interest to the sparse checkout.
echo $subDir >> .git/info/sparse-checkout

git pull Origin master

# Create convenience symlink to the subdirectory of interest
cd ..
ln -s ./.$localRepo$subDir $localRepo
5
jxramos

「スパースチェックアウト」を実行するための.gitconfig[alias]を作成しました。それをチェックしてください(しゃれはありません):

Windowsではcmd.exeで実行します

git config --global alias.sparse-checkout "!f(){ [ $# -eq 2 ] && L=${1##*/} L=${L%.git} || L=$2; mkdir -p \"$L/.git/info\" && cd \"$L\" && git init --template= && git remote add Origin \"$1\" && git config core.sparseCheckout 1; [ $# -eq 2 ] && echo \"$2\" >> .git/info/sparse-checkout || { shift 2; for i; do echo $i >> .git/info/sparse-checkout; done }; git pull --depth 1 Origin master;};f"

さもないと:

git config --global alias.sparse-checkout '!f(){ [ $# -eq 2 ] && L=${1##*/} L=${L%.git} || L=$2; mkdir -p "$L/.git/info" && cd "$L" && git init --template= && git remote add Origin "$1" && git config core.sparseCheckout 1; [ $# -eq 2 ] && echo "$2" >> .git/info/sparse-checkout || { shift 2; for i; do echo $i >> .git/info/sparse-checkout; done }; git pull --depth 1 Origin master;};f'

使用法

# Makes a directory ForStackExchange with Plug checked out
git sparse-checkout https://github.com/YenForYang/ForStackExchange Plug

# To do more than 1 directory, you have to specify the local directory:
git sparse-checkout https://github.com/YenForYang/ForStackExchange ForStackExchange Plug Folder

git configコマンドは、利便性と保存のために「縮小」されていますが、ここではエイリアスが展開されています。

# Note the --template= is for disabling templates.
# Feel free to remove it if you don't have issues with them (like I did)
# `mkdir` makes the .git/info directory ahead of time, as I've found it missing sometimes for some reason
f(){
    [ "$#" -eq 2 ] && L="${1##*/}" L=${L%.git} || L=$2;
    mkdir -p "$L/.git/info"
        && cd "$L"
        && git init --template=
        && git remote add Origin "$1"
        && git config core.sparseCheckout 1;
    [ "$#" -eq 2 ]
        && echo "$2" >> .git/info/sparse-checkout
        || {
            shift 2;
            for i; do
                echo $i >> .git/info/sparse-checkout;
            done
        };
    git pull --depth 1 Origin master;
};
f
1
YenForYang

これは特定のフォルダのクローンを作成し、それに関連しないすべての履歴を削除します。

git clone --single-branch -b {branch} [email protected]:{user}/{repo}.git
git filter-branch --subdirectory-filter {path/to/folder} HEAD
git remote remove Origin
git remote add Origin [email protected]:{user}/{new-repo}.git
git Push -u Origin master
0
BARJ