Last active
January 18, 2025 21:00
-
-
Save ofou/783034a293b68c5391da88def7cfb15d to your computer and use it in GitHub Desktop.
Fill your GitHub calendar with fake commits to confuse recruiters
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 | |
set -euo pipefail | |
# Validate we're in a git repository | |
if ! git rev-parse --git-dir > /dev/null 2>&1; then | |
echo "Error: Not in a git repository" | |
exit 1 | |
fi | |
# Function to validate date format | |
validate_date() { | |
local date="$1" | |
if [[ "$OSTYPE" == "darwin"* ]]; then | |
if ! date -j -f "%Y-%m-%d" "$date" >/dev/null 2>&1; then | |
echo "Error: Invalid date format for '$date'. Please use YYYY-MM-DD" | |
exit 1 | |
fi | |
else | |
if ! date -d "$date" >/dev/null 2>&1; then | |
echo "Error: Invalid date format for '$date'. Please use YYYY-MM-DD" | |
exit 1 | |
fi | |
fi | |
} | |
# Function to get current timezone offset for Chile | |
get_chile_timezone() { | |
# Use system's timezone information to determine current offset | |
TZ="America/Santiago" date +%z | |
} | |
# Function to generate random time between 8:00 and 20:00 (Chilean work hours) | |
generate_random_time() { | |
# Use /dev/urandom for better randomness | |
hour=$((8 + $(od -An -N2 -i /dev/urandom) % 13)) | |
minute=$(($(od -An -N2 -i /dev/urandom) % 60)) | |
second=$(($(od -An -N2 -i /dev/urandom) % 60)) | |
tz_offset=$(get_chile_timezone) | |
printf "%02d:%02d:%02d %s" $hour $minute $second "$tz_offset" | |
} | |
# Function to increment date (macOS compatible) | |
increment_date() { | |
local date="$1" | |
if [[ "$OSTYPE" == "darwin"* ]]; then | |
date -v+1d -j -f "%Y-%m-%d" "$date" "+%Y-%m-%d" | |
else | |
date -d "$date + 1 day" "+%Y-%m-%d" | |
fi | |
} | |
# Function to compare dates (returns 0 if date1 <= date2) | |
compare_dates() { | |
local date1="$1" | |
local date2="$2" | |
if [[ "$OSTYPE" == "darwin"* ]]; then | |
local ts1=$(date -j -f "%Y-%m-%d" "$date1" +%s) | |
local ts2=$(date -j -f "%Y-%m-%d" "$date2" +%s) | |
else | |
local ts1=$(date -d "$date1" +%s) | |
local ts2=$(date -d "$date2" +%s) | |
fi | |
[[ $ts1 -le $ts2 ]] && return 0 || return 1 | |
} | |
# Function to make commits for a specific date | |
make_commits() { | |
local date="$1" | |
# Use modulo on a larger random number for better distribution | |
local commits_to_make=$((1 + $(od -An -N2 -i /dev/urandom) % 5)) | |
echo "Making $commits_to_make commits for $date" | |
for ((i = 1; i <= commits_to_make; i++)); do | |
commit_time=$(generate_random_time) | |
commit_message="Commit $i of $commits_to_make on $date at $commit_time" | |
if ! GIT_AUTHOR_DATE="$date $commit_time" \ | |
GIT_COMMITTER_DATE="$date $commit_time" \ | |
git commit --allow-empty -m "$commit_message"; then | |
echo "Error: Failed to create commit for $date" | |
exit 1 | |
fi | |
done | |
} | |
# Main script | |
start_date="2017-12-01" | |
end_date=$(date +"%Y-%m-%d") | |
# Validate dates | |
validate_date "$start_date" | |
validate_date "$end_date" | |
# Check if end_date is after start_date | |
if ! compare_dates "$start_date" "$end_date"; then | |
echo "Error: End date must be after start date" | |
exit 1 | |
fi | |
# Ensure we're in the right branch and not in detached HEAD | |
current_branch=$(git rev-parse --abbrev-ref HEAD || echo "HEAD") | |
if [ "$current_branch" = "HEAD" ]; then | |
echo "Error: In detached HEAD state" | |
exit 1 | |
elif [ "$current_branch" != "main" ]; then | |
echo "Warning: Not on main branch. Currently on: $current_branch" | |
read -p "Continue anyway? (y/n) " -n 1 -r | |
echo | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
exit 1 | |
fi | |
fi | |
# Print script configuration | |
echo "Configuration:" | |
echo "- Time range: 8:00 AM to 8:00 PM (Chile Time)" | |
echo "- Date range: $start_date to $end_date" | |
echo "- Commits per day: 1-5 (at least 1)" | |
echo "- Timezone: Chile Time (auto-adjusted for DST)" | |
echo | |
# Create a temporary file with restricted permissions to store dates with commits | |
temp_file=$(mktemp) | |
chmod 600 "$temp_file" | |
trap 'rm -f "$temp_file"' EXIT # Ensure temp file is removed on script exit | |
# Get existing commit dates | |
if ! git log --since="$start_date" --until="$end_date" --date=short --pretty=format:"%ad" | sort -u > "$temp_file"; then | |
echo "Error: Failed to retrieve git log" | |
exit 1 | |
fi | |
# Find and process dates without commits | |
echo "Finding dates without commits..." | |
missing_dates=() | |
current_date="$start_date" | |
while compare_dates "$current_date" "$end_date"; do | |
if ! grep -q "^$current_date$" "$temp_file"; then | |
missing_dates+=("$current_date") | |
fi | |
current_date=$(increment_date "$current_date") | |
done | |
# Report the number of dates that need commits | |
total_missing="${#missing_dates[@]}" | |
if [ "$total_missing" -eq 0 ]; then | |
echo "No missing dates found. All days have commits." | |
exit 0 | |
fi | |
echo "Found $total_missing days without commits. Starting to add commits..." | |
# Process each missing date | |
for date in "${missing_dates[@]}"; do | |
make_commits "$date" | |
done | |
# Push changes with error handling | |
echo "Pushing changes to origin..." | |
if ! git push origin "$current_branch"; then | |
echo "Error: Failed to push changes to origin" | |
exit 1 | |
fi | |
echo "Successfully completed all operations!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment