From 9fe6d7d6630dee9ffa17d22c1d3918e996cdc063 Mon Sep 17 00:00:00 2001 From: Robin Winslow Date: Fri, 28 Oct 2016 22:08:59 +0100 Subject: [PATCH] git-force-clone All files for git-force-clone, a command for overwriting local repos when closing repositories. --- Commands.md | 16 +++++ bin/git-force-clone | 107 ++++++++++++++++++++++++++++++++++ etc/git-extras-completion.zsh | 2 +- man/git-force-clone.1 | 57 ++++++++++++++++++ man/git-force-clone.html | 0 man/git-force-clone.md | 56 ++++++++++++++++++ 6 files changed, 237 insertions(+), 1 deletion(-) create mode 100755 bin/git-force-clone create mode 100644 man/git-force-clone.1 create mode 100644 man/git-force-clone.html create mode 100644 man/git-force-clone.md diff --git a/Commands.md b/Commands.md index 9f58bc557..3eed497f6 100644 --- a/Commands.md +++ b/Commands.md @@ -19,6 +19,7 @@ - [`git extras`](#git-extras) - [`git feature|refactor|bug|chore`](#git-featurerefactorbugchore) - [`git fork`](#git-fork) + - [`git force-clone`](#git-force-clone) - [`git fresh-branch`](#git-fresh-branch) - [`git gh-pages`](#git-gh-pages) - [`git graft`](#git-graft) @@ -344,6 +345,21 @@ upstream git@github.com:LearnBoost/expect.js (fetch) upstream git@github.com:LearnBoost/expect.js (push) ``` +## git force-clone + +If the clone target directory exists, reset its contents to a clone of the +remote. + +``` bash +$ git force-clone [-b {branch_name}] {remote_url} {destination_path} +$ git force-clone -b master https://github.com/tj/git-extras ./target-directory +``` + +**CAUTION**: If the repository exists, this will destroy *all* local changes +to the repository - changed files will be reset and local branches will be +removed. + +[More information](man/git-force-clone.md). ## git release diff --git a/bin/git-force-clone b/bin/git-force-clone new file mode 100755 index 000000000..57198167e --- /dev/null +++ b/bin/git-force-clone @@ -0,0 +1,107 @@ +#! /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 git@github.com:me/repo.git ./repo_dir + +Provides the basic functionality of `git clone`, but if the destination +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:-} + ;; + -h | --help ) + _usage + exit 0 + ;; + * ) + if [[ "${1:0:1}" == '-' ]]; then + echo "Error: Invalid option: $1" >>/dev/stderr + _usage + exit 1 + fi + ;; + 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=`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 + ) + else + git clone -b ${branch} ${remote_url} ${destination_path} + fi +} + +main "$@" + +exit 0 diff --git a/etc/git-extras-completion.zsh b/etc/git-extras-completion.zsh index 9465cab3c..03d760d38 100644 --- a/etc/git-extras-completion.zsh +++ b/etc/git-extras-completion.zsh @@ -259,7 +259,6 @@ _git-feature() { esac } - _git-graft() { _arguments \ ':src-branch-name:__gitex_branch_names' \ @@ -373,6 +372,7 @@ zstyle ':completion:*:*:git:*' user-commands \ effort:'show effort statistics on file(s)' \ extras:'awesome git utilities' \ feature:'create/merge feature branch' \ + force-clone:'overwrite local repositories with clone' \ fork:'fork a repo on github' \ fresh-branch:'create fresh branches' \ gh-pages:'create the github pages branch' \ diff --git a/man/git-force-clone.1 b/man/git-force-clone.1 new file mode 100644 index 000000000..ce94f88c2 --- /dev/null +++ b/man/git-force-clone.1 @@ -0,0 +1,57 @@ +.\" generated with Ronn/v0.7.3 +.\" http://github.com/rtomayko/ronn/tree/0.7.3 +. +.TH "GIT\-FORCE\-CLONE" "1" "2016-10-28" "" "Git Extras" +. +.SH "NAME" +\fBgit\-force\-clone\fR \- overwrite local repositories with clone +. +.SH "SYNOPSIS" +\fBforce\-clone \-\-help\fR \fBforce\-clone {remote_url} {destination_path}\fR \fBforce\-clone \-\-branch {branch_name} {remote_url} {destination_path}\fR +. +.SH "DESCRIPTION" +Provides the basic functionality of \fBgit clone\fR, but if the destination repository already exists it will force\-reset it to resemble a clone of the remote\. +. +.P +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\. +. +.P +\fBCAUTION\fR: If the repository exists, this will destroy \fIall\fR local work: changed files will be reset, local branches and other remotes will be removed\. +. +.SH "PROCESS" +If \fBtarget\-directory\fR doesn\'t exist then this will simply be passed through to \fBgit clone\fR, which will clone remote\. +. +.P +If \fBtarget\-directory\fR \fIdoes\fR exist then this will: +. +.IP "\(bu" 4 +Remove all remotes +. +.IP "\(bu" 4 +Set the origin remote to \fB{remote_url}\fR and fetch the remote +. +.IP "\(bu" 4 +Discover the default branch, if no branch was specified +. +.IP "\(bu" 4 +Check out the selected branch +. +.IP "\(bu" 4 +Delete all other local branches +. +.IP "" 0 +. +.SH "OPTIONS" +\fB{remote_url}\fR \- The URL for a git remote repository of which to make a clone\. \fB{destination_path}\fR \- A path to the directory to clone into\. \fB\-\-branch {branch_name}\fR \- After cloning, checkout this branch\. +. +.SH "EXAMPLES" +\fBgit\-force\-clone \-b master git@github\.com:me/repo\.git \./repo_dir\fR +. +.SH "AUTHOR" +Written by Robin Winslow \fIrobin@robinwinslow\.co\.uk\fR\. +. +.SH "REPORTING BUGS" +\fIhttps://github\.com/tj/git\-extras/issues\fR +. +.SH "SEE ALSO" +\fIhttps://github\.com/tj/git\-extras\fR diff --git a/man/git-force-clone.html b/man/git-force-clone.html new file mode 100644 index 000000000..e69de29bb diff --git a/man/git-force-clone.md b/man/git-force-clone.md new file mode 100644 index 000000000..76719d5f5 --- /dev/null +++ b/man/git-force-clone.md @@ -0,0 +1,56 @@ +git-force-clone(1) -- overwrite local repositories with clone +=== + +## SYNOPSIS + +`force-clone --help` +`force-clone {remote_url} {destination_path}` +`force-clone --branch {branch_name} {remote_url} {destination_path}` + +## DESCRIPTION + +Provides the basic functionality of `git clone`, but if the destination +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. + +## PROCESS + +If `target-directory` doesn't exist then this will simply be passed through to +`git clone`, which will clone remote. + +If `target-directory` *does* exist then this will: + +- Remove all remotes +- Set the origin remote to `{remote_url}` and fetch the remote +- Discover the default branch, if no branch was specified +- Check out the selected branch +- Delete all other local branches + +## OPTIONS + +`{remote_url}` - The URL for a git remote repository of which to make a clone. +`{destination_path}` - A path to the directory to clone into. +`--branch {branch_name}` - After cloning, checkout this branch. + +## EXAMPLES + +`git-force-clone -b master git@github.com:me/repo.git ./repo_dir` + +## AUTHOR + +Written by Robin Winslow . + +## REPORTING BUGS + + + +## SEE ALSO + +