-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSplit-GitCommit.ps1
More file actions
220 lines (178 loc) · 6.85 KB
/
Split-GitCommit.ps1
File metadata and controls
220 lines (178 loc) · 6.85 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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
param(
[Parameter(Mandatory=$false)]
[int]$FilesPerCommit = 10,
[Parameter(Mandatory=$false)]
[string]$CommitMessage = "Split commit - batch",
[Parameter(Mandatory=$false)]
[string]$RemoteName = "origin",
[Parameter(Mandatory=$false)]
[string]$BranchName = ""
)
<#
.SYNOPSIS
Splits a large git commit into multiple smaller commits and pushes them to remote.
.DESCRIPTION
This script helps manage large repositories by splitting staged or unstaged changes
into multiple smaller commits. Each commit contains a specified number of files.
After each commit is created, it's automatically pushed to the remote repository.
.PARAMETER FilesPerCommit
Number of files to include in each commit. Default is 10.
.PARAMETER CommitMessage
Base commit message. Each commit will be numbered (e.g., "Split commit - batch 1/5")
.PARAMETER RemoteName
Name of the remote repository. Default is "origin".
.PARAMETER BranchName
Name of the branch to push to. If not specified, uses current branch.
.EXAMPLE
.\Split-GitCommit.ps1 -FilesPerCommit 5
.EXAMPLE
.\Split-GitCommit.ps1 -FilesPerCommit 20 -CommitMessage "Feature update" -RemoteName "upstream"
#>
# Color output functions
function Write-Info {
param([string]$Message)
Write-Host $Message -ForegroundColor Cyan
}
function Write-Success {
param([string]$Message)
Write-Host $Message -ForegroundColor Green
}
function Write-Warning {
param([string]$Message)
Write-Host $Message -ForegroundColor Yellow
}
function Write-ErrorMsg {
param([string]$Message)
Write-Host $Message -ForegroundColor Red
}
# Check if we're in a git repository
function Test-GitRepository {
$gitDir = git rev-parse --git-dir 2>$null
return $LASTEXITCODE -eq 0
}
# Get current branch name
function Get-CurrentBranch {
$branch = git branch --show-current 2>$null
if ($LASTEXITCODE -ne 0) {
throw "Failed to get current branch name"
}
return $branch
}
# Get list of changed files
function Get-ChangedFiles {
# Get both staged and unstaged files
$stagedFiles = git diff --cached --name-only 2>$null
$unstagedFiles = git diff --name-only 2>$null
$untrackedFiles = git ls-files --others --exclude-standard 2>$null
$allFiles = @()
if ($stagedFiles) { $allFiles += $stagedFiles }
if ($unstagedFiles) { $allFiles += $unstagedFiles }
if ($untrackedFiles) { $allFiles += $untrackedFiles }
# Remove duplicates and return
return $allFiles | Select-Object -Unique
}
# Main script execution
try {
Write-Info "================================================"
Write-Info "Git Split Commit and Push Script"
Write-Info "================================================"
Write-Host ""
# Validate we're in a git repository
if (-not (Test-GitRepository)) {
Write-ErrorMsg "Error: Not a git repository. Please run this script from within a git repository."
exit 1
}
Write-Success "✓ Git repository detected"
# Get current branch
if ([string]::IsNullOrEmpty($BranchName)) {
$BranchName = Get-CurrentBranch
Write-Info "Using current branch: $BranchName"
} else {
Write-Info "Target branch: $BranchName"
}
# Get all changed files
Write-Info "Collecting changed files..."
$changedFiles = Get-ChangedFiles
if ($changedFiles.Count -eq 0) {
Write-Warning "No changed files found. Nothing to commit."
exit 0
}
Write-Success "✓ Found $($changedFiles.Count) changed file(s)"
Write-Host ""
# Calculate number of commits needed
$totalCommits = [Math]::Ceiling($changedFiles.Count / $FilesPerCommit)
Write-Info "Configuration:"
Write-Host " Files per commit: $FilesPerCommit"
Write-Host " Total files: $($changedFiles.Count)"
Write-Host " Commits to create: $totalCommits"
Write-Host " Remote: $RemoteName"
Write-Host " Branch: $BranchName"
Write-Host ""
# Confirm with user
$confirmation = Read-Host "Do you want to proceed? (y/n)"
if ($confirmation -ne 'y' -and $confirmation -ne 'Y') {
Write-Warning "Operation cancelled by user."
exit 0
}
Write-Host ""
Write-Info "Starting commit and push process..."
Write-Host ""
# Reset staging area
git reset HEAD . 2>$null | Out-Null
# Process files in batches
$commitCount = 0
for ($i = 0; $i -lt $changedFiles.Count; $i += $FilesPerCommit) {
$commitCount++
$batch = $changedFiles[$i..[Math]::Min($i + $FilesPerCommit - 1, $changedFiles.Count - 1)]
Write-Info "[$commitCount/$totalCommits] Processing batch with $($batch.Count) file(s)..."
# Stage files in this batch
foreach ($file in $batch) {
Write-Host " + $file" -ForegroundColor DarkGray
git add "$file" 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Warning " Warning: Failed to add $file"
}
}
# Create commit
$currentCommitMessage = "$CommitMessage $commitCount/$totalCommits"
Write-Info " Creating commit: $currentCommitMessage"
git commit -m "$currentCommitMessage" 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-ErrorMsg " Error: Failed to create commit"
throw "Commit failed"
}
Write-Success " ✓ Commit created"
# Push to remote
Write-Info " Pushing to $RemoteName/$BranchName..."
git push $RemoteName $BranchName 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-ErrorMsg " Error: Failed to push to remote"
Write-Warning " You may need to manually push or resolve conflicts"
throw "Push failed"
}
Write-Success " ✓ Pushed successfully"
Write-Host ""
}
Write-Host ""
Write-Success "================================================"
Write-Success "✓ All commits completed successfully!"
Write-Success "================================================"
Write-Host ""
Write-Info "Summary:"
Write-Host " Total commits created: $totalCommits"
Write-Host " Total files committed: $($changedFiles.Count)"
Write-Host " All changes pushed to: $RemoteName/$BranchName"
Write-Host ""
} catch {
Write-Host ""
Write-ErrorMsg "================================================"
Write-ErrorMsg "Error occurred: $($_.Exception.Message)"
Write-ErrorMsg "================================================"
Write-Host ""
Write-Warning "The script has stopped. You may need to:"
Write-Host " 1. Check your git status: git status"
Write-Host " 2. Review recent commits: git log --oneline -n 5"
Write-Host " 3. Check remote status: git remote -v"
Write-Host ""
exit 1
}