有没有办法从 git 只下载一个子目录?
Posted
技术标签:
【中文标题】有没有办法从 git 只下载一个子目录?【英文标题】:Is there a way to download only a subdirectory from git? 【发布时间】:2012-10-25 16:46:28 【问题描述】:有没有办法从 git 存储库只下载给定的子目录?假设我只想从 https://github.com/djdeath/toys.git 获取 nyancat
目录。
我可以克隆整个存储库并忽略我不想要的文件,或者转到https://github.com/djdeath/toys/tree/master/nyancat并一一下载相关文件。我认为一定有更简单的方法。
注意我不是在问是否可以克隆目录,这是asked before,显然是不可能的。我只是对快速获取文件感兴趣,不需要重新提交或再次对它们使用 git。
【问题讨论】:
缺乏这种能力是git最糟糕的地方。 【参考方案1】:git-archive
命令几乎可以满足您的需求,但它需要在已经克隆的 repo 上运行,因此如果您可以通过 SSH 访问主机,您可以这样做:
cd /path/to/destination
ssh user@host "cd /path/to/repo && git archive HEAD dir/you/want" | tar xf -
或者,对网络传输进行压缩:
cd /path/to/destination
ssh user@host "cd /path/to/repo && git archive HEAD dir/you/want | gzip" | tar xzf -
【讨论】:
【参考方案2】:嘿,我只是wrote a script
用法
python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>
【讨论】:
【参考方案3】:一个完整的参数化 bash 函数(不依赖)
#!/bin/bash
gitsub()
usage()
cat <<- EOF
------------------------------------------------------------------------
GNU gitsub 0.0.1, a non-interactive github filtered subrepo retriever.
Usage: gitsub [-h] [[-d[dir] -s[strip] -e[ext]] -o owner -r repo -b sub]
------------------------------------------------------------------------
Mandatory arguments to long options are mandatory for short options too.
------------------------------------------------------------------------
MANDATORY:
-o, --owner repo's owner
-r, --repo repo's name
-b, --subrepo directory(s) to be cloned
OPTIONS:
-s, --strip number of dirs (/) to be skipped, default 0
-d, --dir output directory default current directory
-e, --extension filter by ext, if missing clone all (including subdirs)
COMMANDS:
-h, --help display this help and exit
------------------------------------------------------------------------
Mail bug reports and suggestions to makramjandar@gmail.com
------------------------------------------------------------------------
EOF
error() echo -e "\033[1;31mError: $1\033[0m" ;
# check supplied args
is_arg()
[[ -n "$2" && $2:0:1 != "-" ]] \
|| error "Argument for $1 is missing..." >&2 \
&& usage \
&& exit 1 ;
POSITIONAL=()
while (( "$#" )); do
case "$1" in
# commands
-h|--help) usage && exit 0 ;;
# mandatory flags with arguments
-o|--owner) is_arg $1 $2 && OWNER=$2 ; shift 2 ;;
-r|--repo) is_arg $1 $2 && REPO=$2 ; shift 2 ;;
-b|--subrepo) is_arg $1 $2 && SUBREPO=$2 ; shift 2 ;;
# optional flags with arguments
-d|--dir) is_arg $1 $2 && DIR=$2 && mkdir -p $DIR ; shift 2 ;;
-s|--strip) is_arg $1 $2 && STRIP=$2 ; shift 2 ;;
-e|--extension) is_arg $1 $2 && EXTENSION=$2 ; shift 2 ;;
# unsupported flags
-*|--*=) error "Unsupported flag $1" >&2 && usage ; exit 1 ;;
# preserve positional arguments
*) POSITIONAL+=("$1") ; shift ;;
esac
done
# set positional arguments in their proper place
set -- "$POSITIONAL[@]"
# check mandatory arguments
[[ -z "$OWNER" || -z "$REPO" || -z "$SUBREPO" ]] \
&& error "Missing mandatory arguments..." >&2 \
&& usage \
&& exit 1 ;
# get github filtered (optional) subrepository
curl -L "https://api.github.com/repos/$OWNER/$REPO/tarball" \
|
tar \
--verbose \
--extract \
--gzip \
--directory=$DIR:-$PWD \
--strip=$STRIP:-0 \
--wildcards */$SUBREPO/*.$EXTENSION*
2>/dev/null \
&& echo "Done" \
|| \
error "Invalid args..." \
&& usage \
&& exit 1
gitsub "$@"
对于给定的仓库:https://github.com/jenskutilek/free-fonts
下载子文件夹 Fira 的全部内容,包括目录和文件
$ bash gitsub.sh -o "jenskutilek" -r "free-fonts" -b "Fira" -d "FiraUnfiltered" -s 2
$ tree -d FiraUnfiltered/
FiraUnfiltered/
├── Fira Mono
│ ├── OTF
│ ├── TTF
│ ├── VFB
│ └── WOFF
└── Fira Sans
├── OTF
├── TTF
├── VFB
└── WOFF
下载相同的子文件夹,但使用字体 TTF 过滤
$ bash gitsub.sh -o "jenskutilek" -r "free-fonts" -b "Fira" -d "FiraFiltered" -s 2 -e "ttf"
$ tree -d FiraFiltered/
FiraFiltered/
├── Fira Mono
│ └── TTF
└── Fira Sans
└── TTF
通过将 -s|--strip 设置为 4,仅将过滤后的文件下载到 outdir
bash gitsub.sh -o "jenskutilek" -r "free-fonts" -b "Fira" -d "ttfFilesOnly" -s 4 -e "ttf"
$ tree ttfFilesOnly/
ttfFilesOnly/
├── FiraMono-Bold.ttf
├── FiraMono-Regular.ttf
├── FiraSans-Bold.ttf
├── FiraSans-BoldItalic.ttf
├── FiraSans-Light.ttf
├── FiraSans-LightItalic.ttf
├── FiraSans-Medium.ttf
├── FiraSans-MediumItalic.ttf
├── FiraSans-Regular.ttf
└── FiraSans-RegularItalic.ttf
【讨论】:
你应该稍微解释一下你的脚本。 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。 我的函数提供了嵌入式帮助...我应该打印它还是必须为帮助本身重写第二个帮助!有点一致性,请先生 @Ale 我的意思是编辑答案,而不是添加评论添加答案的详细信息。以上是关于有没有办法从 git 只下载一个子目录?的主要内容,如果未能解决你的问题,请参考以下文章
在 Windows 7 Git Bash 中,有没有办法探索当前位置的目录?