Created
October 19, 2025 01:40
-
-
Save dsfaccini/239136e5c2690e2750f0cb64e7defc46 to your computer and use it in GitHub Desktop.
How do I clone a sub directory from a github repository? This script clones only a specific folder from a git(hub) repository, without history, then deletes the repository and inits a new one. This is particularly useful for cloning templates.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # add this line to you .zshrc to make the command globally available: | |
| # source ~/.shell-functions/clone-git-folder.zsh | |
| # you'll need to open a new shell or run source ~/.zshrc to reload your shell config | |
| # | |
| # usage example: the template for deploying payloadcms on cloudflare | |
| # running `clone-git-folder https://github.com/payloadcms/payload/tree/main/templates/with-cloudflare-d1` | |
| # will create a new folder called "with-cloudflare-d1" | |
| # running `clone-git-folder https://github.com/payloadcms/payload/tree/main/templates/with-cloudflare-d1 payloadcms-on-cloudflare` | |
| # will create a new folder called "payloadcms-on-cloudflare" | |
| clone-git-folder() { | |
| # Usage: | |
| # clone-git-folder <github_folder_url> [<new_folder_name>] | |
| # clone-git-folder <repo_url> <path/in/repo> [<new_folder_name>] | |
| if [[ $# -lt 1 ]]; then | |
| echo "Usage:" | |
| echo " clone-git-folder <github_folder_url> [<new_folder_name>]" | |
| echo " clone-git-folder <repo_url> <path/in/repo> [<new_folder_name>]" | |
| return 1 | |
| fi | |
| local REPO_URL FOLDER_PATH DEST | |
| if [[ "$1" =~ "github.com/([^/]+)/([^/]+)/tree/([^/]+)/(.*)" ]]; then | |
| # GitHub URL mode (zsh regex -> $match) | |
| local OWNER="${match[1]}" | |
| local REPO="${match[2]}" | |
| local BRANCH="${match[3]}" # not used, but parsed for correctness | |
| FOLDER_PATH="${match[4]}" | |
| REPO_URL="https://github.com/${OWNER}/${REPO}.git" | |
| DEST="${2:-$(basename "$FOLDER_PATH")}" | |
| elif [[ $# -ge 2 ]]; then | |
| # Manual mode | |
| REPO_URL="$1" | |
| FOLDER_PATH="$2" | |
| DEST="${3:-$(basename "$FOLDER_PATH")}" | |
| else | |
| echo "β Missing folder path argument." | |
| echo "Usage: clone-git-folder <repo_url> <path/in/repo> [<new_folder_name>]" | |
| return 1 | |
| fi | |
| local CWD TMP_DIR | |
| CWD="$(pwd)" | |
| TMP_DIR="$(mktemp -d)" | |
| echo "π¦ Cloning '$FOLDER_PATH' from $REPO_URL ..." | |
| git clone --depth 1 --filter=blob:none --sparse "$REPO_URL" "$TMP_DIR" >/dev/null 2>&1 || { | |
| echo "β git clone failed" | |
| rm -rf "$TMP_DIR" | |
| return 1 | |
| } | |
| # Limit checkout to the target folder (run inside tmp, but don't change caller's dir) | |
| ( cd "$TMP_DIR" && git sparse-checkout set "$FOLDER_PATH" >/dev/null 2>&1 ) || { | |
| echo "β Folder '$FOLDER_PATH' not found in repo" | |
| rm -rf "$TMP_DIR" | |
| return 1 | |
| } | |
| # Copy into destination under the ORIGINAL directory; include dotfiles | |
| mkdir -p "$CWD/$DEST" | |
| ( cd "$TMP_DIR/$FOLDER_PATH" && tar -cf - . ) | ( cd "$CWD/$DEST" && tar -xf - ) | |
| # Clean up tmp | |
| rm -rf "$TMP_DIR" | |
| # Nuke any git metadata that might have been copied and init fresh repo | |
| rm -rf "$CWD/$DEST/.git" | |
| git -C "$CWD/$DEST" init -q | |
| echo "β Folder '$FOLDER_PATH' cloned into '$DEST' (fresh git repo) β staying in $(pwd)" | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment