From 202830ede45df0a9121019011b5f0b478ae4c9bb Mon Sep 17 00:00:00 2001 From: Srinivasan T M Date: Wed, 17 Jan 2024 10:44:19 +0530 Subject: [PATCH 1/6] Sparse checkout script to selectively clone folders from a repo --- git/sparse_checkout.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 git/sparse_checkout.sh diff --git a/git/sparse_checkout.sh b/git/sparse_checkout.sh new file mode 100644 index 0000000..97c5b9f --- /dev/null +++ b/git/sparse_checkout.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +URL=$1 + +if [ -z "$1" ]; then + echo "Usage [REMOTE-URL]" + exit 1 +fi + +REMOTE="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\1/\2/\3.git|p')" +MAIN_DIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\3|p')" +SUBDIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\4|p')" + +test -d "$MAIN_DIR" || mkdir "$MAIN_DIR" +cd "$MAIN_DIR" || exit +test -d .git || git init --initial-branch=main +if [ "$(git remote show | wc -l)" = "0" ]; then + git remote add origin "$REMOTE" +fi +git config core.sparseCheckout true +if test -f .git/info/sparse-checkout; then + git sparse-checkout add "$SUBDIR" +else + git sparse-checkout set "$SUBDIR" +fi +git pull origin main --depth=1 --ff-only || git pull origin master --depth=1 --ff-only +cd .. From 456f80b52b90ba4c07e4a05ff91727b2768e42f0 Mon Sep 17 00:00:00 2001 From: Srinivasan T M <=> Date: Mon, 22 Jan 2024 11:39:10 +0530 Subject: [PATCH 2/6] Added branch argument for sparse_checkout * Optionally include branch to pull from, defaults to "main" --- git/sparse_checkout.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/git/sparse_checkout.sh b/git/sparse_checkout.sh index 97c5b9f..2c96ad8 100644 --- a/git/sparse_checkout.sh +++ b/git/sparse_checkout.sh @@ -1,6 +1,7 @@ #!/bin/bash URL=$1 +BRANCH=${2:-"main"} if [ -z "$1" ]; then echo "Usage [REMOTE-URL]" @@ -13,7 +14,7 @@ SUBDIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\4 test -d "$MAIN_DIR" || mkdir "$MAIN_DIR" cd "$MAIN_DIR" || exit -test -d .git || git init --initial-branch=main +test -d .git || git init --initial-branch="$BRANCH" if [ "$(git remote show | wc -l)" = "0" ]; then git remote add origin "$REMOTE" fi @@ -23,5 +24,5 @@ if test -f .git/info/sparse-checkout; then else git sparse-checkout set "$SUBDIR" fi -git pull origin main --depth=1 --ff-only || git pull origin master --depth=1 --ff-only +git pull origin "$BRANCH" --depth=1 --ff-only cd .. From 5b6b523082bce743f33852cdb51e5169b37f18c2 Mon Sep 17 00:00:00 2001 From: Srinivasan T M <=> Date: Mon, 22 Jan 2024 11:46:46 +0530 Subject: [PATCH 3/6] Added relevant comments, and modified help message --- git/sparse_checkout.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/git/sparse_checkout.sh b/git/sparse_checkout.sh index 2c96ad8..0cf0f67 100644 --- a/git/sparse_checkout.sh +++ b/git/sparse_checkout.sh @@ -4,16 +4,24 @@ URL=$1 BRANCH=${2:-"main"} if [ -z "$1" ]; then - echo "Usage [REMOTE-URL]" + echo "Usage [REMOTE-URL] [BRANCH]" + echo "BRANCH argument is optional: defaults to main" exit 1 fi +# This specifies the remote URL from which to fetch from REMOTE="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\1/\2/\3.git|p')" + +# This specifies the directory name that is to be created MAIN_DIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\3|p')" + +# This specifies which subdirectory to selectively clone SUBDIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\4|p')" test -d "$MAIN_DIR" || mkdir "$MAIN_DIR" cd "$MAIN_DIR" || exit + +# reference: https://stackoverflow.com/questions/600079/how-do-i-clone-a-subdirectory-only-of-a-git-repository test -d .git || git init --initial-branch="$BRANCH" if [ "$(git remote show | wc -l)" = "0" ]; then git remote add origin "$REMOTE" @@ -25,4 +33,5 @@ else git sparse-checkout set "$SUBDIR" fi git pull origin "$BRANCH" --depth=1 --ff-only + cd .. From e4e897cbe7aa153b05a9340199e7be66ac39849a Mon Sep 17 00:00:00 2001 From: Srinivasan T M <=> Date: Mon, 5 Feb 2024 16:09:00 +0530 Subject: [PATCH 4/6] Removed unnecessary failsafe * cd || exit is a popular pattern to make sure your program exits if cd fails, but there is no change cd fails in this scenario as we are performing mkdir in the previous step, so removing "|| exit" --- git/sparse_checkout.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/sparse_checkout.sh b/git/sparse_checkout.sh index 0cf0f67..bc15d4a 100644 --- a/git/sparse_checkout.sh +++ b/git/sparse_checkout.sh @@ -19,7 +19,7 @@ MAIN_DIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)| SUBDIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\4|p')" test -d "$MAIN_DIR" || mkdir "$MAIN_DIR" -cd "$MAIN_DIR" || exit +cd "$MAIN_DIR" # reference: https://stackoverflow.com/questions/600079/how-do-i-clone-a-subdirectory-only-of-a-git-repository test -d .git || git init --initial-branch="$BRANCH" From af0343ec5565d17fb9109cb427f4a843731a20ad Mon Sep 17 00:00:00 2001 From: Srinivasan T M <=> Date: Wed, 21 Feb 2024 18:43:12 +0530 Subject: [PATCH 5/6] Approaching sparse checkout in a different method --- git/sparse_checkout.sh | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/git/sparse_checkout.sh b/git/sparse_checkout.sh index bc15d4a..4c69ce0 100644 --- a/git/sparse_checkout.sh +++ b/git/sparse_checkout.sh @@ -1,37 +1,30 @@ #!/bin/bash -URL=$1 -BRANCH=${2:-"main"} +REMOTE_URL=$1 +SUBDIR=$2 +BRANCH=${3:-"main"} -if [ -z "$1" ]; then - echo "Usage [REMOTE-URL] [BRANCH]" +if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage [REMOTE-URL] [SUBDIRECTORY] [BRANCH]" echo "BRANCH argument is optional: defaults to main" exit 1 fi -# This specifies the remote URL from which to fetch from -REMOTE="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\1/\2/\3.git|p')" - # This specifies the directory name that is to be created -MAIN_DIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\3|p')" +MAIN_DIR="$(echo "$REMOTE_URL" | sed -n 's|\(.*com\)/\([^/]*\)/\([^/]*\)|\3|p')" -# This specifies which subdirectory to selectively clone -SUBDIR="$(echo "$URL" | sed -n 's|\(.*github.com\)/\([^/]*\)/\([^/]*\)/\(.*\)|\4|p')" +# reference: https://stackoverflow.com/questions/4114887/is-it-possible-to-do-a-sparse-checkout-without-checking-out-the-whole-repository -test -d "$MAIN_DIR" || mkdir "$MAIN_DIR" +test -d "$MAIN_DIR" || git clone --filter=blob:none --no-checkout --depth 1 --sparse "$REMOTE_URL" cd "$MAIN_DIR" - -# reference: https://stackoverflow.com/questions/600079/how-do-i-clone-a-subdirectory-only-of-a-git-repository -test -d .git || git init --initial-branch="$BRANCH" -if [ "$(git remote show | wc -l)" = "0" ]; then - git remote add origin "$REMOTE" -fi git config core.sparseCheckout true -if test -f .git/info/sparse-checkout; then - git sparse-checkout add "$SUBDIR" +if test -f .git/info/sparse-checkout; then + [ "$(grep -c "$SUBDIR" .git/info/sparse-checkout)" -eq 0 ] && git sparse-checkout add "$SUBDIR" else git sparse-checkout set "$SUBDIR" fi -git pull origin "$BRANCH" --depth=1 --ff-only + +git checkout --force +git pull origin "$BRANCH" --depth=1 --rebase cd .. From 7aa5a2808865092c69644e06f7685346f3507ce2 Mon Sep 17 00:00:00 2001 From: Srinivasan T M Date: Wed, 21 Feb 2024 22:09:48 +0530 Subject: [PATCH 6/6] Fixed issue where running this script on a sparse-checkout branch with missing files did not restore the missing files + fixed issue where running this script did not pull remote changes to local --- git/sparse_checkout.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git/sparse_checkout.sh b/git/sparse_checkout.sh index 4c69ce0..409801c 100644 --- a/git/sparse_checkout.sh +++ b/git/sparse_checkout.sh @@ -17,14 +17,14 @@ MAIN_DIR="$(echo "$REMOTE_URL" | sed -n 's|\(.*com\)/\([^/]*\)/\([^/]*\)|\3|p')" test -d "$MAIN_DIR" || git clone --filter=blob:none --no-checkout --depth 1 --sparse "$REMOTE_URL" cd "$MAIN_DIR" + git config core.sparseCheckout true if test -f .git/info/sparse-checkout; then [ "$(grep -c "$SUBDIR" .git/info/sparse-checkout)" -eq 0 ] && git sparse-checkout add "$SUBDIR" else git sparse-checkout set "$SUBDIR" fi - git checkout --force -git pull origin "$BRANCH" --depth=1 --rebase +git pull origin "$BRANCH" --depth=1 --rebase --force cd ..