-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit-squash.sh
More file actions
executable file
·149 lines (128 loc) · 4.33 KB
/
git-squash.sh
File metadata and controls
executable file
·149 lines (128 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/bin/bash
# Parse command line arguments
commit_message=""
repo_list_file=""
repos_directory=""
while [[ $# -gt 0 ]]; do
case $1 in
-m|--message)
commit_message="$2"
shift 2
;;
*)
if [ -z "$repo_list_file" ]; then
repo_list_file="$1"
elif [ -z "$repos_directory" ]; then
repos_directory="$1"
else
echo "Error: Too many arguments"
exit 1
fi
shift
;;
esac
done
if [ -z "$repo_list_file" ] || [ -z "$repos_directory" ]; then
echo "Usage: $0 [-m|--message <message>] <repo_list_file> <repos_directory>"
echo " -m, --message: Commit message (if not provided, will prompt for each repo)"
echo " repo_list_file: Path to file containing repository names (one per line)"
echo " repos_directory: Path to directory containing the repositories"
exit 1
fi
if [ ! -f "$repo_list_file" ]; then
echo "Error: Repository list file '$repo_list_file' not found"
exit 1
fi
if [ ! -d "$repos_directory" ]; then
echo "Error: Repositories directory '$repos_directory' not found"
exit 1
fi
while IFS= read -r repo_name; do
# Skip empty lines and comments
if [[ -z "$repo_name" || "$repo_name" =~ ^# ]]; then
continue
fi
repo_path="$repos_directory/$repo_name"
if [ ! -d "$repo_path" ]; then
echo "Warning: Repository '$repo_name' not found at $repo_path"
continue
fi
if [ ! -d "$repo_path/.git" ]; then
echo "Warning: '$repo_name' is not a git repository"
continue
fi
echo "=== $repo_name ==="
cd "$repo_path" || continue
# Get current branch
current_branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$current_branch" = "HEAD" ]; then
echo " Warning: Repository is in detached HEAD state - skipping"
echo
continue
fi
# Don't squash if we're already on master
if [ "$current_branch" = "master" ]; then
echo " Already on master branch - skipping"
echo
continue
fi
# Find merge base (divergence point) with origin/master (or master if origin/master doesn't exist)
merge_base=$(git merge-base origin/master HEAD 2>/dev/null || git merge-base master HEAD 2>/dev/null)
if [ -z "$merge_base" ]; then
echo " Warning: Cannot find merge base with origin/master - skipping"
echo
continue
fi
# Check if there are commits to squash
commit_count=$(git rev-list --count "$merge_base..HEAD")
if [ "$commit_count" -eq 0 ]; then
echo " No commits to squash - branch is up to date with master"
echo
continue
fi
if [ "$commit_count" -eq 1 ]; then
echo " Found 1 commit to update message since master"
else
echo " Found $commit_count commits to squash since master"
fi
echo " Commits to be squashed:"
git log --oneline "$merge_base..HEAD" | sed 's/^/ /'
# Check for staged changes (unstaged changes are fine since we're doing soft reset)
if ! git diff-index --quiet --cached HEAD --; then
echo " Warning: Staged changes detected - please commit or reset first"
echo
continue
fi
# Get commit message
if [ -z "$commit_message" ]; then
echo -n " Enter commit message for $repo_name: "
read -r user_message
if [ -z "$user_message" ]; then
echo " Skipping squash (no message provided)"
echo
continue
fi
current_message="$user_message"
else
current_message="$commit_message"
fi
# Perform soft reset to merge base
if git reset --soft "$merge_base"; then
echo " Reset to merge base successfully"
else
echo -e " \033[31mFailed to reset to merge base\033[0m"
echo
continue
fi
# Create new commit with all changes
if git commit -m "$current_message"; then
if [ "$commit_count" -eq 1 ]; then
echo -e " \033[32mUpdated commit message successfully\033[0m"
else
echo -e " \033[32mSquashed $commit_count commits successfully\033[0m"
fi
else
echo -e " \033[31mFailed to create squashed commit\033[0m"
fi
echo
done < "$repo_list_file"