Last active
December 5, 2023 05:37
-
-
Save Zoybean/8db78966abea5d974934bb0e8e5f4e42 to your computer and use it in GitHub Desktop.
For when you've got a local git repo that's just too hard to recover
This file contains 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
#!/bin/bash | |
# Author: Zoey Llewellyn "Zobean" Hewll | |
# | |
# Usage: fix-git [REMOTE-URL] | |
# Must be run from the root directory of the repository. | |
# If a remote is not supplied, it will be read from .git/config | |
# | |
# For when you have a corrupted local repo, but a trusted remote. | |
# This script replaces all your history with that of the remote. | |
# If there is a .git, it is backed up as .git_old, removing the last backup. | |
# This does not affect your working tree. | |
# | |
# This does not currently work with submodules! | |
# This will abort if a suspected submodule is found. | |
# You will have to delete them first | |
# and re-clone them after (with `git submodule update --init`) | |
# | |
# Error codes: | |
# 1: If a url is not supplied, and one cannot be read from .git/config | |
# 4: If the url cannot be reached | |
# 5: If a git submodule is detected | |
if [[ "$(find -name .git -not -path ./.git | wc -l)" -gt 0 ]] ; | |
then | |
echo "It looks like this repo uses submodules" >&2 | |
echo "You will need to remove them before this script can safely execute" >&2 | |
echo "Then use \`git submodule update --init\` to re-clone them" >&2 | |
exit 5 | |
fi | |
if [[ $# -ge 1 ]] ; | |
then | |
url="$1" | |
else | |
if ! url="$(git config --local --get remote.origin.url)" ; | |
then | |
echo "Unable to find remote 'origin': missing in '.git/config'" >&2 | |
exit 1 | |
fi | |
fi | |
url_base="$(echo "${url}" | sed -E 's;^([^/]*://)?([^/]*)(/.*)?$;\2;')" | |
echo "Attempting to access ${url_base} before continuing" | |
if ! wget -p "${url_base}" -O /dev/null -q --dns-timeout=5 --connect-timeout=5 ; | |
then | |
echo "Unable to reach ${url_base}: Aborting before any damage is done" >&2 | |
exit 4 | |
fi | |
echo | |
echo "This operation will replace the local repo with the remote at:" | |
echo "${url}" | |
echo | |
echo "This will completely rewrite history," | |
echo "but will leave your working tree intact" | |
echo -n "Are you sure? (y/N): " | |
read confirm | |
if ! [ -t 0 ] ; # i'm open in a pipe | |
then | |
# print the piped input | |
echo "${confirm}" | |
fi | |
if echo "${confirm}"|grep -Eq "[Yy]+[EeSs]*" ; # it looks like a yes | |
then | |
if [[ -e .git ]] ; | |
then | |
# remove old backup | |
rm -vrf .git_old | tail -n 1 && | |
# backup .git iff it exists | |
mv -v .git .git_old | |
fi && | |
git init && | |
git remote add origin "${url}" && | |
git config --local --get remote.origin.url | sed 's/^/Added remote origin at /' && | |
git fetch && | |
git reset origin/master --mixed | |
else | |
echo "Aborting without doing anything" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The script doesn't setup the remote tracking branch correctly after reinitialising. you have to also "git branch --set-upstream-to=origin/<branchname> <branchname>" given origin is the remote's name