私のGitリポジトリには、ルートに2つのサブディレクトリがあります。
/finisht
/static
これが _ svn _ にある場合、/finisht
は1か所でチェックアウトされ、/static
は別の場所でチェックアウトされました。
svn co svn+ssh://[email protected]/home/admin/repos/finisht/static static
Gitでこれを行う方法はありますか?
_ 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 を使ってそれらを一緒に接着することができます。
あなたがやろうとしていることは 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 を参照してください。
疎チェックアウト と シャロークローン の機能を組み合わせることができます。 浅いクローン は履歴を切り捨て、 疎なチェックアウト はパターンに一致するファイルのみを引き出します。
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
では不可能です。
ただダウンロードしたい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
}
注 このメソッドはフォルダをダウンロードし、それを複製/チェックアウトしません。変更をリポジトリにプッシュバックすることはできません。一方、スパースチェックアウトやシャローチェックアウトに比べて、ダウンロード数は少なくなります。
複製元のリポジトリとやり取りする予定がない場合は、完全な git clone を実行し、 git filter-branch --subdirectory-filter を使用してリポジトリを書き換えることができます。このように、少なくとも歴史は保存されるでしょう。
Git 1.7.0には「スパースチェックアウト」があります。 git config manpage の「core.sparseCheckout」、 git read-tree manpage の「Sparse checkout」、および「skip-worktreeビット」を参照してください。 git update-index manページ にあります。
インターフェースはSVNのものほど便利ではありません(例えば、初期のクローン作成時にスパースチェックアウトをする方法はありません)が、より単純なインターフェースを構築するための基本機能は現在利用可能です。
これ ははるかに単純に見えます。
git archive --remote=<repo_url> <branch> <path> | tar xvf -
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に伝えることができます。
通常どおりにリポジトリのクローンを作成します(--no-checkout
はオプションです)。
git clone --no-checkout git@foo/bar.git
cd bar
リポジトリが既にクローンされている場合は、この手順を飛ばしてもかまいません。
ヒント:大規模なリポジトリでは、 シャロークローン (--depth 1
)を検討して最新のリビジョンまたは/および--single-branch
のみをチェックアウトします。
sparseCheckout
オプションを有効にします。
git config core.sparseCheckout true
疎チェックアウト用のフォルダを指定します( 末尾に スペースなし)。
echo "trunk/public_html/*"> .git/info/sparse-checkout
または.git/info/sparse-checkout
を編集します。
ブランチをチェックアウトします(例:master
)。
git checkout master
これで、現在のディレクトリ内のフォルダを選択したはずです。
ディレクトリのレベルが多すぎる場合や、ブランチをフィルタリングする場合は、シンボリックリンクを検討してください。
これは、単一サブディレクトリの疎チェックアウトの使用例として私が書いたシェルスクリプトです
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
「スパースチェックアウト」を実行するための.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
これは特定のフォルダのクローンを作成し、それに関連しないすべての履歴を削除します。
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