#!/bin/bash # ============================================================================== # Script Description: # This script connects an existing local directory to a remote Git repository. # # Process: # 1. Initializes a new local Git repository. # 2. Adds the remote 'origin'. # 3. Fetches the remote repository data. # 4. Stages local files to check differences. # 5. Identifies real changes bypassing the Git --name-only whitespace bug. # 6. Prompts to override local files if diffs are found. # # Updated: Includes intelligent .gitignore handling (local vs remote comparison). # ============================================================================== if [ -z "$1" ]; then echo "Error: No repository SSH URL provided." echo "Usage: $0 " exit 1 fi REPO_URL=$1 BRANCH="master" echo "Initializing Git repository..." git init echo "Adding remote 'origin' -> $REPO_URL" git remote add origin "$REPO_URL" echo "Fetching from origin..." git fetch origin # --- .GITIGNORE LOGIC --- REMOTE_IGNORE_TEMP=$(mktemp) if git show "origin/$BRANCH:.gitignore" > "$REMOTE_IGNORE_TEMP" 2>/dev/null; then if [ -f .gitignore ]; then # Check if local and remote versions are actually different if ! diff -q .gitignore "$REMOTE_IGNORE_TEMP" > /dev/null; then echo "---" echo "NOTICE: .gitignore conflict detected." echo "Differences ( - Local / + Remote ):" diff -u .gitignore "$REMOTE_IGNORE_TEMP" | tail -n +3 echo "---" read -p "Overwrite local .gitignore with the remote version? (y/N): " ignore_choice case "$ignore_choice" in [yY]* ) mv "$REMOTE_IGNORE_TEMP" .gitignore echo "Replaced with remote .gitignore." ;; * ) echo "Keeping local .gitignore. Note: This may cause extra files to show in the diff below." rm "$REMOTE_IGNORE_TEMP" ;; esac else echo "Local and remote .gitignore are identical." rm "$REMOTE_IGNORE_TEMP" fi else echo "No local .gitignore found. Applying remote version..." mv "$REMOTE_IGNORE_TEMP" .gitignore fi else echo "No .gitignore found on remote. Proceeding with existing local state..." rm -f "$REMOTE_IGNORE_TEMP" fi # --------------------------------- echo "Staging local files so Git can compare them..." # Clear cache first to ensure we aren't tracking things the new .gitignore should skip git rm -r --cached . > /dev/null 2>&1 git add . echo "Checking for differences (ignoring line-endings and whitespace)..." if git diff --cached --quiet --ignore-cr-at-eol --ignore-space-at-eol "origin/$BRANCH"; then echo "Local folder matches remote origin/$BRANCH exactly." else echo "" echo "Differences exist in the following files:" # We use --numstat instead of --name-only. # Files with only whitespace diffs will output '0 \t 0 \t filename'. # Awk filters out the ones where added ($1) and deleted ($2) are both 0. # Note: Binary changes show as '-' rather than '0', which awk will correctly keep. git diff --cached --numstat --ignore-cr-at-eol --ignore-space-at-eol "origin/$BRANCH" | \ awk -F'\t' '$1!="0" || $2!="0" {print $3}' echo "" read -p "Do you want to discard your local changes and accept the remote version for these files? (y/N): " choice case "$choice" in [yY]* ) echo "Accepting remote versions..." ;; * ) echo "Operation aborted by user." echo "You can review full diffs manually by running: git diff --cached --ignore-cr-at-eol --ignore-space-at-eol origin/$BRANCH" exit 1 ;; esac fi echo "Setting up tracking and aligning with remote..." # 1. First ensure we are on the correct branch name git checkout -B "$BRANCH" # 2. Reset hard FIRST so the branch actually has commits git reset --hard "origin/$BRANCH" # 3. NOW set the upstream tracking, since the branch is no longer empty git branch --set-upstream-to="origin/$BRANCH" "$BRANCH" echo "Success! The local folder is now completely linked to the remote repository."