Last active
June 6, 2026 14:18
-
-
Save glowinthedark/ae6bfbd0624caafa5123a6a688ba944c to your computer and use it in GitHub Desktop.
git-repository-truncate-to-single-commit.sh
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
| #!/usr/bin/env bash | |
| # git_truncate.sh | |
| # Truncates current branch to a single commit (squashes all history) | |
| # and force-pushes to origin. | |
| # Usage: ./git_truncate.sh [remote_name] | |
| # Default remote: origin | |
| set -euo pipefail | |
| REMOTE="${1:-origin}" | |
| BRANCH="$(git rev-parse --abbrev-ref HEAD)" | |
| REPO_ROOT="$(git rev-parse --show-toplevel)" | |
| REPO_NAME="$(basename "$REPO_ROOT")" | |
| BACKUP_PATH="$(dirname "$REPO_ROOT")/${REPO_NAME}_ORIGINAL" | |
| echo "" | |
| echo "⚠️ WARNING: This will PERMANENTLY and IRRECOVERABLY rewrite $REPO_ROOT and force-push to $REMOTE/$BRANCH." | |
| read -rp " Create a backup at ${BACKUP_PATH}? [y/N]: " CONFIRM_BACKUP | |
| if [[ "$CONFIRM_BACKUP" =~ ^[Yy]$ ]]; then | |
| echo "[0] Backing up repo to $BACKUP_PATH ..." | |
| cp -r "$REPO_ROOT" "$BACKUP_PATH" | |
| echo "[0] Backup complete." | |
| else | |
| echo "[0] Skipping backup." | |
| fi | |
| echo "[1] Current branch: $BRANCH | Remote: $REMOTE" | |
| # Capture the current tree state and author/committer info | |
| TREE=$(git write-tree) | |
| TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") | |
| COMMITTER_NAME=$(git config user.name 2>/dev/null || echo "Truncated") | |
| COMMITTER_EMAIL=$(git config user.email 2>/dev/null || echo "truncated@localhost") | |
| echo "[2] Writing orphan commit over current tree..." | |
| # Create a new root commit with no parents, pointing at current working tree | |
| NEW_COMMIT=$(git commit-tree "$TREE" -m "Initial commit (history truncated on $TIMESTAMP)") | |
| echo "[3] New root commit: $NEW_COMMIT" | |
| # Move HEAD and branch ref to the new orphan commit | |
| git reset --hard "$NEW_COMMIT" | |
| echo "[4] Local branch reset to single commit." | |
| # Force push — rewrites remote history | |
| echo "" | |
| echo "⚠️ DESTRUCTIVE: about to force-push to $REMOTE/$BRANCH — all remote history will be permanently lost." | |
| read -rp " Type '$BRANCH' to confirm: " CONFIRM | |
| if [ "$CONFIRM" != "$BRANCH" ]; then | |
| echo "Aborted. Local repo has already been reset; remote is untouched." | |
| exit 1 | |
| fi | |
| echo "[5] Force pushing to $REMOTE/$BRANCH ..." | |
| git push "$REMOTE" "$BRANCH" --force | |
| echo "" | |
| echo "Done. Repo now has exactly $(git rev-list --count HEAD) commit(s) on $BRANCH." | |
| git --no-pager log --oneline | |
| echo 'IMPORTANT: Everyone who cloned the original repo NOW MUST RUN: | |
| git fetch origin | |
| git reset --hard origin/master | |
| ^^^^ !!! THIS WILL ZAP ALL LOCAL UNCOMMITTED OR COMMITTED (BUT UNPUSHED) CHANGES | |
| ' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment