Skip to content

Instantly share code, notes, and snippets.

@locopine
Forked from nottrobin/git-force-clone.sh
Created March 23, 2022 22:27
Show Gist options
  • Save locopine/02d2a62d5839f2f8565ca06761c4d988 to your computer and use it in GitHub Desktop.
Save locopine/02d2a62d5839f2f8565ca06761c4d988 to your computer and use it in GitHub Desktop.
git force-clone: clone a repository; if it already exists locally, reset it to a clone of the remote.
#! /usr/bin/env bash
set -euo pipefail
_usage() {
echo "
Usage:
git-force-clone -b branch remote_url destination_path
Example:
git-force-clone -b master [email protected]:me/repo.git ./repo_dir
Provides the basic functionality of 'git clone', but if the destination git
repository already exists it will force-reset it to resemble a clone of the
remote.
Because it doesn't actually delete the directory, it is usually significantly
faster than the alternative of deleting the directory and cloning the
repository from scratch.
**CAUTION**: If the repository exists, this will destroy *all* local work:
changed files will be reset, local branches and other remotes will be removed.
OPTIONS:
-b, --branch The branch to pull from the remote (default: master)
-h, --help Display this help message
"
}
_check() {
if [ -z "$1" ]; then
echo "Error: Missing ${2}"
_usage
exit 1
fi
}
main() {
while [[ -n "${1:-}" ]] && [[ "${1:0:1}" == "-" ]]; do
case $1 in
-b | --branch )
branch=${2:-}
shift
;;
-h | --help )
_usage
exit 0
;;
* )
echo "Error: Invalid option: $1" >>/dev/stderr
_usage
exit 1
;;
esac
shift
done
remote_url=${1:-}
destination_path=${2:-}
_check "${remote_url}" "remote_url"
_check "${destination_path}" "destination_path"
if [ -d "${destination_path}/.git" ]; then
(
cd ${destination_path}
# Delete all remotes
for remote in `git remote`; do
git remote rm ${remote}
done
# Add origin
git remote add origin ${remote_url}
git fetch origin
# Set default branch
if [ -z "${branch:-}" ]; then
branch=`LC_ALL=C git remote show origin | grep -oP '(?<=HEAD branch: )[^ ]+$'`
git remote set-head origin ${branch}
else
git remote set-head origin -a
fi
# Make sure current branch is clean
git clean -fd
git reset --hard HEAD
# Get on the desired branch
git checkout ${branch}
git reset --hard origin/${branch}
# Delete all other branches
branches=`git branch | grep -v \* | xargs`
if [ -n "${branches}" ]; then
git branch -D ${branches}
fi
)
elif [ -n "${branch:-}" ]; then
git clone -b ${branch} ${remote_url} ${destination_path}
else
git clone ${remote_url} ${destination_path}
fi
}
main "$@"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment