Gitリポジトリのみのサブディレクトリのクローンを作成するにはどうすればよいですか?


1410

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

/finisht
/static

これがSVN/finishtあったとき、次のように1か所で/staticチェックアウトされ、他の場所でチェックアウトされました。

svn co svn+ssh://admin@domain.com/home/admin/repos/finisht/static static

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



1
2014年のユーザーにとって、git clone最も簡単なコマンドは何ですか?私はこの単純な答えを使いました。もっと簡単なものがあれば、コメントしてください
Peter Krauss、2014年

(ルートフォルダーを作成せずに)リポジトリのコンテンツのクローンを作成しようとする場合、これは非常に簡単な解決策です。stackoverflow.com
Marc

@JoachimBreitner:その質問はGitのサブディレクトリをチェックアウトすること(簡単です)に関するものですが、この質問はGitのサブディレクトリのクローン作成(これは不可能です)に関するものです。
イェルクWミッターク

@NickSergeant:3週間前にリリースのGit 2.19のように、これはこの答えに見られるように、最終的には可能である:stackoverflow.com/a/52269934/2988 1になりましたことを受け入れることを検討してください。注:Git 2.19では、クライアント側のサポートのみが実装されており、サーバー側のサポートはまだ存在しないため、ローカルリポジトリのクローンを作成する場合にのみ機能します。また、GitHubなどの大規模なGitホスターは実際にはGitサーバーを使用せず、独自の実装を使用しているため、Gitサーバーでサポートが表示されても、Gitホスターで動作するとは限りません。(OTOH、彼らはより速く、それを実装することができます。)
イェルクWミッターク

回答:


612

編集:Git 2.19現在、これは最終的に可能です。これは、この回答に示されています

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

注:Git 2.19では、クライアント側のサポートのみが実装されており、サーバー側のサポートはまだ存在しないため、ローカルリポジトリのクローンを作成する場合にのみ機能します。また、GitHubなどの大規模なGitホスティング業者は実際にはGitサーバーを使用せず、独自の実装を使用しているため、Gitサーバーでサポートが表示されても、Gitホスティング業者で自動的に機能するとは限りません。(OTOH、Gitサーバーを使用しないため、Gitサーバーに表示される前に、独自の実装でより速く実装できます。)


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

このようなものをGitに実装することはかなりの労力であり、クライアント側リポジトリの整合性が保証されなくなることを意味します。興味がある場合は、gitメーリングリストで「sparse clone」と「sparse fetch」に関するディスカッションを検索してください。

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


6
シナリオによっては、gitサブモジュールの代わりにgitサブツリーを使用したい場合があります。alumnit.ca/~apenwarr/log/?m=200904#30を
C Pirate

9
@StijndeWitt:まばらなチェックアウトが中git-read-treeに発生しget-fetchます。問題はサブディレクトリだけをチェックアウトすることではなく、サブディレクトリだけを複製することでした。git-read-treeクローンが既に完了した後で実行されるため、スパースチェックアウトがどのように実行できるかはわかりません。
イェルクWミッターク

9
この「スタブ」ではなく、この回答を削除して、Chronialが上に浮かぶようにしますか?承認されているため、自分で削除することはできませんが、モデレーターは削除できます。それはとても古いので、あなたはそれから得た評判を維持するでしょう。誰かが「リンクのみ」としてそれをフラグが立てられているため(私はこの出くわした:-)。
コーディグレー

1
@CodyGray:Chronial答えはまだ全体のリポジトリをクローンしていないだけで、サブディレクトリを。(最後の段落では明示的にそう言っています。)Git ではサブディレクトリのみの複製はできません。ネットワークプロトコルはそれをサポートしていません、ストレージフォーマットはそれをサポートしていません。この質問に対するすべての答えは、常にリポジトリ全体を複製します。質問は単純なはい/いいえの質問であり、答えは2文字です:いいえ。仮に私の答えは不必要に長く、短くはありません。
イェルクWミッターク

1
@JörgWMittag:Ciro Santili の答えはあなたと矛盾しているようです。
Dan Dascalescu

1525

あなたがやろうとしていることはスパースチェックアウトと呼ばれ、その機能はgit 1.7.0(2012年2月)で追加されました。スパースクローンを作成する手順は次のとおりです。

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/diranother/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"

これでもサーバーからリポジトリ全体がダウンロードされます。チェックアウトのサイズのみが縮小されます。現時点では、単一のディレクトリのみを複製することはできません。ただし、リポジトリの履歴が必要ない場合は、浅いクローンを作成することで、少なくとも帯域幅を節約できます。参照してくださいudondanの答え浅い結合する方法については、下記のクローンとまばらなチェックアウトを。


git 2.25.0(2020年1月)以降、実験的なsparse-checkoutコマンドがgitに追加されています。

git sparse-checkout init
# same as: 
git config core.sparseCheckout true

git sparse-checkout set "A/B"
# same as:
echo "A/B" >> .git/info/sparse-checkout

git sparse-checkout list
# same as:
cat .git/info/sparse-checkout

14
Appleでは '-f'境界は機能しません。-fなしでgit remote add origin <url>を実行するだけ
Anno2001

135
これは改善ですが、リモートリポジトリの完全なコピーを元の場所にダウンロードして保存する必要があります。コードベースの一部のみに関心がある場合(または私の場合のようにドキュメントサブフォルダーがある場合)は、これをまったく回避する必要があります。 )
a1an 2013年

56
(ディレクトリ自体ではなく)目的のディレクトリコンテンツをリポジトリにクローンする方法はありますか?たとえば、https://github.com/Umkus/nginx-boilerplate/tree/master/srcright intoのコンテンツをクローンしたい/etc/nginx
mac

25
@ Chronial、@ ErikE:あなたはどちらも正しい/間違っています:P git remote addコマンドはフェッチを意味しませgit remote add -f、ここで使用されているように、そうです!それが-f意味です。
ntc2 2014年

21
これと --depth=1 4.9 GBの完全なBlinkソース+履歴ではなく、338 MBでChromium Devtoolsのクローンを作成しました。優秀な。
ルディー、2014年

444

git clone --filter Git 2.19から

このオプションは、実際にはサーバーからの不要なオブジェクトのフェッチをスキップします。--filter=tree:0Git 2.20--filter=combineGit 2.24で追加された複合フィルターも含めて、次のようになります。

git clone \
  --depth 1 \
  --filter=combine:blob:none+tree:0 \
  --no-checkout \
  "file://$(pwd)/server_repo" \
  local_repo \
;
cd local_repo
git checkout master -- mydir/

サーバーは次のように構成する必要があります。

git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

この機能をサポートしv2.19.0、実際には不要なオブジェクトのフェッチをスキップするために、Gitリモートプロトコルが拡張されましたが、現時点ではサーバーはサポートされていません。しかし、それはすでにローカルでテストすることができます。

コマンドの内訳:

のフォーマット --filterは、に記載されていman git-rev-listます。

Gitツリーのドキュメント:

試してみる

#!/usr/bin/env bash
set -eu

list-objects() (
  git rev-list --all --objects
  echo "master commit SHA: $(git log -1 --format="%H")"
  echo "mybranch commit SHA: $(git log -1 --format="%H")"
  git ls-tree master
  git ls-tree mybranch | grep mybranch
  git ls-tree master~ | grep root
)

# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

rm -rf server_repo local_repo
mkdir server_repo
cd server_repo

# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet

# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet

# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet

echo "# List and identify all objects"
list-objects
echo

# Restore master.
git checkout --quiet master
cd ..

# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo

# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo

echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo

echo "# Git checkout fetches the missing directory from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/
echo

echo "# Missing objects after checking out d1"
git rev-list --all --quiet --objects --missing=print

GitHubアップストリーム

Git v2.19.0での出力:

# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75    d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a    d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3    master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043    mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f    root

# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63

# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

# Missing objects after checking out d1
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb

結論:外部からのすべてのblob d1/がありません。たとえば0975df9b39e23c15f63db194df7f45c76528bccbd2/bチェックアウト後ありませんd1/a

とも欠落しroot/rootmybranch/mybranchいることに注意してください。--depth 1、欠落ファイルのリストには表示されません。を削除すると--depth 1、見つからないファイルのリストに表示されます。

私には夢があります

この機能はGitに革命をもたらす可能性があります。

次のような醜いサードパーティツールを使用せずに、企業のすべてのコードベースを単一のリポジトリに格納することを想像してください。repo

醜いサードパーティの拡張機能なしで、巨大なブロブを直接リポジトリに格納することを想像してください。

GitHubがスターやアクセス許可などのファイル/ディレクトリごとのメタデータを許可する場合を想像してください。これにより、すべての個人的なものを1つのリポジトリに保存できます。

サブモジュールが通常のディレクトリとまったく同じように扱われると想像してみてください。ツリーのSHAを要求するだけで、DNSのようなメカニズムが要求を解決し、最初にローカルを~/.git調べ、次により近いサーバー(企業のミラー/キャッシュ)を探し、GitHubで終わります。


奇妙なことに、gitバージョン2.20.1(Apple Git-117)を搭載したmacOSでは、「複数のフィルター仕様を組み合わせることはできない」という
メッセージ

1
悲しいことに、macOS gitバージョンでは運がありません。fatal: invalid filter-spec 'combine:blob:none+tree:0'とにかくありがとう!多分それは新しいバージョンで動作します。
muru

1
これは、GIT 2.24.1を使用してWindows 10で試行すると失敗します(「sha1ファイルを読み取れません。Linuxで同じバージョンのチャームとして動作しました。
Oyvind

1
@Ciro Santilli gitバージョン2.26.1.windows.1では、「...のsha1ファイルを読み取れません」というエラーが引き続き発生します。バグレポートを開いた:github.com/git-for-windows/git/issues/2590
nharrer

1
@nharrer情報をありがとう!
Ciro Santilli冠状病毒审查六四事件法轮功

405

スパースチェックアウトシャロークローン機能を組み合わせることができます。浅いクローンの歴史と遮断まばらなチェックアウトは、あなたのパターンにマッチするファイルを取得します。

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でのみ自分でテストしました。

このようにすると、引き続きをプッシュできますが、では不可能git archiveです。


21
これは便利であり、利用可能な最良の回答である可能性がありますが、チェックアウトに表示されなくても、気にしていないコンテンツ(プルするブランチにある場合)を複製します。
nobar 2015

1
あなたのgitバージョンは何ですか?gitのヘルプによると、深度オプションは利用できますか?
うどんだん2015

2
最後のコマンドがないときに私のために動作しませんgit pull --depth=1 origin masterけどgit pull --depth=1 origin <any-other-branch>。これはとても奇妙で、ここで私の質問を参照してください。stackoverflow.com/questions/35820630/...
シューマン

5
Windowsでは、最後から2番目の行で引用符を省略しないと、プルが失敗します。
nateirvin 2016年

4
これでもすべてのデータがダウンロードされます!svnを使用してこのソリューションを見つけました:stackoverflow.com/a/18324458/2302437
electronix384128

157

githubからファイル/フォルダーをダウンロードたい他のユーザーは、単に以下を使用します:

svn export <repo>/trunk/<folder>

例えば

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

(はい、それはここではsvnです。どうやら2016年にはまだgitvnファイルを単にダウンロードするためにまだsvnが必要です)

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

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

bashスクリプトとして:

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

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


9
githubで私のために働いた唯一のバージョン。gitコマンドは> 10kファイルをチェックアウトしました。svnは私が欲しかった700だけをエクスポートします。ありがとう!
ChristopherLörken2017

4
これを試してみましhttps://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacityたが、svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't existエラーが発生しました:(
zthomas.nc

9
@ zthomas.nc udacityの前の「トランク」を削除し、代わりに/ tree / master /を/ trunk /に置き換える必要があります。
スピーディ

2
このコマンドは私のために働いたものでした!ローカルで変更できるように、レポからファイルのコピーを取得したいだけです。救いへの古き良きSVN!
Michael J

3
動作しますが、遅いようです。開始するのに少し時間がかかり、その後ファイルは比較的ゆっくりとロールします
Aryeh Beitz

73

クローン元のリポジトリとやり取りする予定がない場合は、完全なgitクローンを作成しgit filter-branch --subdirectory-filterを使用してリポジトリを書き直すことができます。このようにして、少なくとも履歴は保持されます。


11
コマンドを知らない人のために、それはgit filter-branch --subdirectory-filter <subdirectory>
ハイメ・ハブルツェル2014年

9
この方法には、選択したサブディレクトリが新しいリポジトリのルートになるという利点があります。
Andrew Schulman

それは間違いなく最良で最も簡単な使用方法です。これは、サブディレクトリフィルターを使用したワンステップのコマンドですgit clone https://github.com/your/repo_xx.git && cd repo_xx && git filter-branch --subdirectory-filter repo_xx_subdir
Alex

66

これははるかに簡単に見えます:

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

17
githubでこれを行うと、致命的になります。操作はプロトコルでサポートされていません。予期しないコマンドストリームの終了
Michael Fox 14

1
プロトコルエラーの原因としては、HTTPSまたは:リポジトリのURLが考えられます。また、sshキーがないことが原因である可能性もあります。
Umair A. 14

2
githubを使用している場合はsvn export代わりに使用できます
Milo Wielondek

2
Githubで動作しない->無効なコマンド: 'git-upload-archive' xxx / yyy.git '' sshを使用してgit:// URLのクローンを作成しているようです。core.gitProxy構成オプションとGIT_PROXY_COMMAND環境変数が設定されていないことを確認してください。致命的:リモートエンドが突然ハングアップした
Nianliang

3
これがGitHubで機能しない理由:「git-archiveを使用してGitHubから直接アーカイブをプルすることはサポートされていません。リポジトリをローカルで複製してgit-archiveを実行するか、または[ZIPをダウンロード]ボタンをクリックしてください。リポジトリページ。」 github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
Donn Lee

63

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

インターフェースはSVNほど便利ではありませんが(たとえば、最初のクローン時にスパースチェックアウトを行う方法はありません)、より単純なインターフェースを構築できる基本機能が利用できるようになりました。


37

Gitだけでサブディレクトリを複製することはできませんが、以下はいくつかの回避策です。

フィルターブランチ

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

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

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

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


スパースチェックアウト

作業ディレクトリをまばらに配置するスパースチェックアウトアプローチの簡単な手順を以下に示します。これにより、作業ディレクトリ内のどのフォルダーまたはファイルをチェックアウトする価値があるかを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
    

これで、現在のディレクトリにフォルダーが選択されました。

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



うのフィルタブランチはまだあなたができるようにしますかpull
SAM

2
@sam:いいえ。 filter-branch親のコミットを書き換えて、それらが異なるSHA1 IDを持つようにします。したがって、フィルタリングされたツリーには、リモートツリーと共通のコミットはありません。 git pullどこからマージしようとするか分からないでしょう。
Peter Cordes 2017年

このアプローチは、主に私のケースに対する満足のいく答えです。
Abbas

10

GitHubのスクリプト書いたところです。

使用法:

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

11
参考までに、これはGitHub専用です。
Sz。

9
そして、明らかにこれはディレクトリをダウンロードするためのものであり、すべてのメタデータを含むリポジトリの一部を複製するものではありません...
LarsH

5
ここにコードを含め、他の場所には含めないでください。
jww 2018

urllib2.HTTPError:HTTPエラー403:レート制限を超えました
diyism

9

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

git clone --single-branch -b {branch} git@github.com:{user}/{repo}.git
git filter-branch --subdirectory-filter {path/to/folder} HEAD
git remote remove origin
git remote add origin git@github.com:{user}/{new-repo}.git
git push -u origin master

ここでドラゴンになります。あなたは迎えますWARNING:gitのフィルタ分岐は、マングルされた歴史の書き換えを生成落とし穴の供給過剰を持っています...。次に、 git-filter-branch docsにはかなり長い警告リストがあります。
Oyvind

6

これは、単一のサブディレクトリのスパースチェックアウトの使用例のために私が作成したシェルスクリプトです。

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

2
素敵なスクリプト、修正する必要があるのはシンボリックリンクだけです。ln -s ./.$localRepo/$subDir $localRepo代わりにすべき ですln -s ./.$localRepo$subDir $localRepo
valentin_nasta '16年

2

.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

なぜこれが機能するのですL=${1##*/} L=${L%.git}か?スペースはオペレーターですか?
Gulzt

2

Linuxを使用していますか?アクセスしやすく、作業ツリーをクリーンアップしたいだけですか?マシン上の残りのコードを気にすることなく。シンボリックリンクを試してください!

git clone https://github.com:{user}/{repo}.git ~/my-project
ln -s ~/my-project/my-subfolder ~/Desktop/my-subfolder

テスト

cd ~/Desktop/my-subfolder
git status

1

ここでいくつかの素晴らしい答えを明確にするために、答えの多くで概説されている手順は、すでにどこかにリモートリポジトリがあることを前提としています。

:与えられた例えば、既存のgitリポジトリgit@github.com:some-user/full-repo.gitあなたが引くしたいことを1つ以上のディレクトリで、独立して、レポの残りの例えばディレクトリが命名app1し、app2

上記のようなgitリポジトリがあると仮定します...

次に、次のような手順を実行して、より大きなリポジトリから特定のディレクトリのみを取得できます。

mkdir app1
cd app1
git init
git remote add origin git@github.com:some-user/full-repo.git
git config core.sparsecheckout true
echo "app1/" >> .git/info/sparse-checkout
git pull origin master

疎チェックアウトオプションを元のリポジトリに設定する必要があると誤って考えました。これは事実ではありません。リモートから取得する前に、ローカルに必要なディレクトリを定義します。この説明が他の人の役に立つことを願っています。


0

git reposを処理するときに実際にsvnを使用する必要があるのは嫌いですが、//これはいつも使用しています。

function git-scp() (
  URL="$1" && shift 1
  svn export ${URL/blob\/master/trunk}
)

これにより、変更なしでgithub urlからコピーできます。使用法;

--- /tmp » git-scp https://github.com/dgraph-io/dgraph/blob/master/contrib/config/kubernetes/helm                                                                                                                  1 ↵
A    helm
A    helm/Chart.yaml
A    helm/README.md
A    helm/values.yaml
Exported revision 6367.

--- /tmp » ls | grep helm
Permissions Size User    Date Modified    Name
drwxr-xr-x     - anthony 2020-01-07 15:53 helm/

0

ディレクトリの最新のリビジョンファイルに本当に興味がある場合は、Githubを使用すると、履歴を含まないZipファイルとしてリポジトリをダウンロードできます。したがって、ダウンロードは非常に高速です。


0

だから私はこのトレッドですべてを試しましたが、何もうまくいきませんでした... Gitのバージョン2.24(この回答の時点でcpanelに付属しているもの)では、これを行う必要はありません

echo "wpm/*" >> .git/info/sparse-checkout

必要なのはフォルダ名だけです

wpm/*

つまり、簡単に言うと

git config core.sparsecheckout true

次に、.git / info / sparse-checkoutを編集し、最後に/ *を付けてフォルダー名(1行に1つ)を追加して、サブフォルダーとファイルを取得します

wpm/*

チェックアウトコマンドを保存して実行する

git checkout master

結果は、私のリポジトリから予期されたフォルダであり、これがあなたのために機能した場合は何も賛成しませんでした

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.