Skip to content

Commit 544c724

Browse files
committed
fix: initial commit error
1 parent b892985 commit 544c724

File tree

2 files changed

+126
-16
lines changed

2 files changed

+126
-16
lines changed

server/routes/git.js

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,34 +80,47 @@ async function validateGitRepository(projectPath) {
8080
// Get git status for a project
8181
router.get('/status', async (req, res) => {
8282
const { project } = req.query;
83-
83+
8484
if (!project) {
8585
return res.status(400).json({ error: 'Project name is required' });
8686
}
8787

8888
try {
8989
const projectPath = await getActualProjectPath(project);
90-
90+
9191
// Validate git repository
9292
await validateGitRepository(projectPath);
9393

94-
// Get current branch
95-
const { stdout: branch } = await execAsync('git rev-parse --abbrev-ref HEAD', { cwd: projectPath });
96-
94+
// Get current branch - handle case where there are no commits yet
95+
let branch = 'main';
96+
let hasCommits = true;
97+
try {
98+
const { stdout: branchOutput } = await execAsync('git rev-parse --abbrev-ref HEAD', { cwd: projectPath });
99+
branch = branchOutput.trim();
100+
} catch (error) {
101+
// No HEAD exists - repository has no commits yet
102+
if (error.message.includes('unknown revision') || error.message.includes('ambiguous argument')) {
103+
hasCommits = false;
104+
branch = 'main';
105+
} else {
106+
throw error;
107+
}
108+
}
109+
97110
// Get git status
98111
const { stdout: statusOutput } = await execAsync('git status --porcelain', { cwd: projectPath });
99-
112+
100113
const modified = [];
101114
const added = [];
102115
const deleted = [];
103116
const untracked = [];
104-
117+
105118
statusOutput.split('\n').forEach(line => {
106119
if (!line.trim()) return;
107-
120+
108121
const status = line.substring(0, 2);
109122
const file = line.substring(3);
110-
123+
111124
if (status === 'M ' || status === ' M' || status === 'MM') {
112125
modified.push(file);
113126
} else if (status === 'A ' || status === 'AM') {
@@ -118,19 +131,20 @@ router.get('/status', async (req, res) => {
118131
untracked.push(file);
119132
}
120133
});
121-
134+
122135
res.json({
123-
branch: branch.trim(),
136+
branch,
137+
hasCommits,
124138
modified,
125139
added,
126140
deleted,
127141
untracked
128142
});
129143
} catch (error) {
130144
console.error('Git status error:', error);
131-
res.json({
132-
error: error.message.includes('not a git repository') || error.message.includes('Project directory is not a git repository')
133-
? error.message
145+
res.json({
146+
error: error.message.includes('not a git repository') || error.message.includes('Project directory is not a git repository')
147+
? error.message
134148
: 'Git operation failed',
135149
details: error.message.includes('not a git repository') || error.message.includes('Project directory is not a git repository')
136150
? error.message
@@ -264,6 +278,50 @@ router.get('/file-with-diff', async (req, res) => {
264278
}
265279
});
266280

281+
// Create initial commit
282+
router.post('/initial-commit', async (req, res) => {
283+
const { project } = req.body;
284+
285+
if (!project) {
286+
return res.status(400).json({ error: 'Project name is required' });
287+
}
288+
289+
try {
290+
const projectPath = await getActualProjectPath(project);
291+
292+
// Validate git repository
293+
await validateGitRepository(projectPath);
294+
295+
// Check if there are already commits
296+
try {
297+
await execAsync('git rev-parse HEAD', { cwd: projectPath });
298+
return res.status(400).json({ error: 'Repository already has commits. Use regular commit instead.' });
299+
} catch (error) {
300+
// No HEAD - this is good, we can create initial commit
301+
}
302+
303+
// Add all files
304+
await execAsync('git add .', { cwd: projectPath });
305+
306+
// Create initial commit
307+
const { stdout } = await execAsync('git commit -m "Initial commit"', { cwd: projectPath });
308+
309+
res.json({ success: true, output: stdout, message: 'Initial commit created successfully' });
310+
} catch (error) {
311+
console.error('Git initial commit error:', error);
312+
313+
// Handle the case where there's nothing to commit
314+
if (error.message.includes('nothing to commit')) {
315+
return res.status(400).json({
316+
error: 'Nothing to commit',
317+
details: 'No files found in the repository. Add some files first.'
318+
});
319+
}
320+
321+
res.status(500).json({ error: error.message });
322+
}
323+
});
324+
267325
// Commit changes
268326
router.post('/commit', async (req, res) => {
269327
const { project, message, files } = req.body;

src/components/GitPanel.jsx

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function GitPanel({ selectedProject, isMobile, onFileOpen }) {
3232
const [isPublishing, setIsPublishing] = useState(false);
3333
const [isCommitAreaCollapsed, setIsCommitAreaCollapsed] = useState(isMobile); // Collapsed by default on mobile
3434
const [confirmAction, setConfirmAction] = useState(null); // { type: 'discard|commit|pull|push', file?: string, message?: string }
35+
const [isCreatingInitialCommit, setIsCreatingInitialCommit] = useState(false);
3536
const textareaRef = useRef(null);
3637
const dropdownRef = useRef(null);
3738

@@ -547,7 +548,7 @@ function GitPanel({ selectedProject, isMobile, onFileOpen }) {
547548

548549
const handleCommit = async () => {
549550
if (!commitMessage.trim() || selectedFiles.size === 0) return;
550-
551+
551552
setIsCommitting(true);
552553
try {
553554
const response = await authenticatedFetch('/api/git/commit', {
@@ -559,7 +560,7 @@ function GitPanel({ selectedProject, isMobile, onFileOpen }) {
559560
files: Array.from(selectedFiles)
560561
})
561562
});
562-
563+
563564
const data = await response.json();
564565
if (data.success) {
565566
// Reset state after successful commit
@@ -577,6 +578,32 @@ function GitPanel({ selectedProject, isMobile, onFileOpen }) {
577578
}
578579
};
579580

581+
const createInitialCommit = async () => {
582+
setIsCreatingInitialCommit(true);
583+
try {
584+
const response = await authenticatedFetch('/api/git/initial-commit', {
585+
method: 'POST',
586+
headers: { 'Content-Type': 'application/json' },
587+
body: JSON.stringify({
588+
project: selectedProject.name
589+
})
590+
});
591+
592+
const data = await response.json();
593+
if (data.success) {
594+
fetchGitStatus();
595+
fetchRemoteStatus();
596+
} else {
597+
console.error('Initial commit failed:', data.error);
598+
alert(data.error || 'Failed to create initial commit');
599+
}
600+
} catch (error) {
601+
console.error('Error creating initial commit:', error);
602+
alert('Failed to create initial commit');
603+
} finally {
604+
setIsCreatingInitialCommit(false);
605+
}
606+
};
580607

581608
const getStatusLabel = (status) => {
582609
switch (status) {
@@ -1161,6 +1188,31 @@ function GitPanel({ selectedProject, isMobile, onFileOpen }) {
11611188
<div className="flex items-center justify-center h-32">
11621189
<RefreshCw className="w-6 h-6 animate-spin text-gray-400" />
11631190
</div>
1191+
) : gitStatus?.hasCommits === false ? (
1192+
<div className="flex flex-col items-center justify-center p-8 text-center">
1193+
<GitBranch className="w-16 h-16 mb-4 opacity-30 text-gray-400 dark:text-gray-500" />
1194+
<h3 className="text-lg font-medium mb-2 text-gray-900 dark:text-white">No commits yet</h3>
1195+
<p className="text-sm text-gray-500 dark:text-gray-400 mb-6 max-w-md">
1196+
This repository doesn't have any commits yet. Create your first commit to start tracking changes.
1197+
</p>
1198+
<button
1199+
onClick={createInitialCommit}
1200+
disabled={isCreatingInitialCommit}
1201+
className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
1202+
>
1203+
{isCreatingInitialCommit ? (
1204+
<>
1205+
<RefreshCw className="w-4 h-4 animate-spin" />
1206+
<span>Creating Initial Commit...</span>
1207+
</>
1208+
) : (
1209+
<>
1210+
<GitCommit className="w-4 h-4" />
1211+
<span>Create Initial Commit</span>
1212+
</>
1213+
)}
1214+
</button>
1215+
</div>
11641216
) : !gitStatus || (!gitStatus.modified?.length && !gitStatus.added?.length && !gitStatus.deleted?.length && !gitStatus.untracked?.length) ? (
11651217
<div className="flex flex-col items-center justify-center h-32 text-gray-500 dark:text-gray-400">
11661218
<GitCommit className="w-12 h-12 mb-2 opacity-50" />

0 commit comments

Comments
 (0)