feat: add rename branch functionality with UI integration
This commit is contained in:
@@ -1696,6 +1696,22 @@ pub async fn create_branch(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn rename_branch(
|
||||||
|
directory: String,
|
||||||
|
old_name: String,
|
||||||
|
new_name: String,
|
||||||
|
state: State<'_, DesktopRuntime>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let root = validate_git_path(&directory, state.settings())
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
run_git(&["branch", "-m", &old_name, &new_name], &root)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn get_git_log(
|
pub async fn get_git_log(
|
||||||
directory: String,
|
directory: String,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use commands::files::{create_directory, exec_commands, list_directory, read_file, search_files, write_file};
|
use commands::files::{create_directory, exec_commands, list_directory, read_file, search_files, write_file};
|
||||||
use commands::git::{
|
use commands::git::{
|
||||||
add_git_worktree, check_is_git_repository, checkout_branch, create_branch, create_git_commit,
|
add_git_worktree, check_is_git_repository, checkout_branch, create_branch, create_git_commit, rename_branch,
|
||||||
create_git_identity, delete_git_branch, delete_git_identity, delete_remote_branch,
|
create_git_identity, delete_git_branch, delete_git_identity, delete_remote_branch,
|
||||||
ensure_openchamber_ignored, generate_commit_message, get_commit_files,
|
ensure_openchamber_ignored, generate_commit_message, get_commit_files,
|
||||||
get_current_git_identity, get_git_branches, get_git_diff, get_git_file_diff,
|
get_current_git_identity, get_git_branches, get_git_diff, get_git_file_diff,
|
||||||
@@ -863,6 +863,7 @@ fn main() {
|
|||||||
git_fetch,
|
git_fetch,
|
||||||
checkout_branch,
|
checkout_branch,
|
||||||
create_branch,
|
create_branch,
|
||||||
|
rename_branch,
|
||||||
get_git_log,
|
get_git_log,
|
||||||
get_commit_files,
|
get_commit_files,
|
||||||
get_git_identities,
|
get_git_identities,
|
||||||
|
|||||||
@@ -183,6 +183,15 @@ export const createDesktopGitAPI = (): GitAPI => ({
|
|||||||
return { success: true, branch: name };
|
return { success: true, branch: name };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async renameBranch(directory: string, oldName: string, newName: string): Promise<{ success: boolean; branch: string }> {
|
||||||
|
await safeGitInvoke<void>('rename_branch', {
|
||||||
|
directory,
|
||||||
|
oldName,
|
||||||
|
newName
|
||||||
|
});
|
||||||
|
return { success: true, branch: newName };
|
||||||
|
},
|
||||||
|
|
||||||
async getGitLog(directory: string, options?: GitLogOptions): Promise<GitLogResponse> {
|
async getGitLog(directory: string, options?: GitLogOptions): Promise<GitLogResponse> {
|
||||||
return safeGitInvoke<GitLogResponse>('get_git_log', {
|
return safeGitInvoke<GitLogResponse>('get_git_log', {
|
||||||
directory,
|
directory,
|
||||||
|
|||||||
@@ -424,6 +424,21 @@ export const GitView: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRenameBranch = async (oldName: string, newName: string) => {
|
||||||
|
if (!currentDirectory) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await git.renameBranch(currentDirectory, oldName, newName);
|
||||||
|
toast.success(`Renamed branch ${oldName} to ${newName}`);
|
||||||
|
await refreshStatusAndBranches();
|
||||||
|
await refreshLog();
|
||||||
|
} catch (err) {
|
||||||
|
const message =
|
||||||
|
err instanceof Error ? err.message : `Failed to rename branch ${oldName} to ${newName}`;
|
||||||
|
toast.error(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleCheckoutBranch = async (branch: string) => {
|
const handleCheckoutBranch = async (branch: string) => {
|
||||||
if (!currentDirectory) return;
|
if (!currentDirectory) return;
|
||||||
const normalized = branch.replace(/^remotes\//, '');
|
const normalized = branch.replace(/^remotes\//, '');
|
||||||
@@ -652,6 +667,7 @@ export const GitView: React.FC = () => {
|
|||||||
onPush={() => handleSyncAction('push')}
|
onPush={() => handleSyncAction('push')}
|
||||||
onCheckoutBranch={handleCheckoutBranch}
|
onCheckoutBranch={handleCheckoutBranch}
|
||||||
onCreateBranch={handleCreateBranch}
|
onCreateBranch={handleCreateBranch}
|
||||||
|
onRenameBranch={handleRenameBranch}
|
||||||
activeIdentityProfile={activeIdentityProfile}
|
activeIdentityProfile={activeIdentityProfile}
|
||||||
availableIdentities={availableIdentities}
|
availableIdentities={availableIdentities}
|
||||||
onSelectIdentity={handleApplyIdentity}
|
onSelectIdentity={handleApplyIdentity}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { BranchSelector } from './BranchSelector';
|
import { BranchSelector } from './BranchSelector';
|
||||||
|
import { WorktreeBranchDisplay } from './WorktreeBranchDisplay';
|
||||||
import { SyncActions } from './SyncActions';
|
import { SyncActions } from './SyncActions';
|
||||||
import type { GitStatus, GitIdentityProfile } from '@/lib/api/types';
|
import type { GitStatus, GitIdentityProfile } from '@/lib/api/types';
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ interface GitHeaderProps {
|
|||||||
onPush: () => void;
|
onPush: () => void;
|
||||||
onCheckoutBranch: (branch: string) => void;
|
onCheckoutBranch: (branch: string) => void;
|
||||||
onCreateBranch: (name: string) => Promise<void>;
|
onCreateBranch: (name: string) => Promise<void>;
|
||||||
|
onRenameBranch?: (oldName: string, newName: string) => Promise<void>;
|
||||||
activeIdentityProfile: GitIdentityProfile | null;
|
activeIdentityProfile: GitIdentityProfile | null;
|
||||||
availableIdentities: GitIdentityProfile[];
|
availableIdentities: GitIdentityProfile[];
|
||||||
onSelectIdentity: (profile: GitIdentityProfile) => void;
|
onSelectIdentity: (profile: GitIdentityProfile) => void;
|
||||||
@@ -187,6 +189,7 @@ export const GitHeader: React.FC<GitHeaderProps> = ({
|
|||||||
onPush,
|
onPush,
|
||||||
onCheckoutBranch,
|
onCheckoutBranch,
|
||||||
onCreateBranch,
|
onCreateBranch,
|
||||||
|
onRenameBranch,
|
||||||
activeIdentityProfile,
|
activeIdentityProfile,
|
||||||
availableIdentities,
|
availableIdentities,
|
||||||
onSelectIdentity,
|
onSelectIdentity,
|
||||||
@@ -199,7 +202,12 @@ export const GitHeader: React.FC<GitHeaderProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="flex flex-wrap items-center gap-2 border-b border-border/40 px-3 py-2 bg-background">
|
<header className="flex flex-wrap items-center gap-2 border-b border-border/40 px-3 py-2 bg-background">
|
||||||
{!isWorktreeMode && (
|
{isWorktreeMode ? (
|
||||||
|
<WorktreeBranchDisplay
|
||||||
|
currentBranch={status.current}
|
||||||
|
onRename={onRenameBranch}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<BranchSelector
|
<BranchSelector
|
||||||
currentBranch={status.current}
|
currentBranch={status.current}
|
||||||
localBranches={localBranches}
|
localBranches={localBranches}
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { RiGitBranchLine, RiEditLine, RiCheckLine, RiCloseLine, RiLoader4Line } from '@remixicon/react';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
|
interface WorktreeBranchDisplayProps {
|
||||||
|
currentBranch: string | null | undefined;
|
||||||
|
onRename?: (oldName: string, newName: string) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sanitizeBranchNameInput = (value: string): string => {
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(/\s+/g, '-')
|
||||||
|
.replace(/[^A-Za-z0-9._/-]/g, '-')
|
||||||
|
.replace(/-+/g, '-')
|
||||||
|
.replace(/\/{2,}/g, '/')
|
||||||
|
.replace(/\/-+/g, '/')
|
||||||
|
.replace(/-+\//g, '/')
|
||||||
|
.replace(/^[-/]+/, '')
|
||||||
|
.replace(/[-/]+$/, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WorktreeBranchDisplay: React.FC<WorktreeBranchDisplayProps> = ({
|
||||||
|
currentBranch,
|
||||||
|
onRename,
|
||||||
|
}) => {
|
||||||
|
const [isEditing, setIsEditing] = React.useState(false);
|
||||||
|
const [editBranchName, setEditBranchName] = React.useState(currentBranch || '');
|
||||||
|
const [isRenaming, setIsRenaming] = React.useState(false);
|
||||||
|
const inputRef = React.useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const handleStartEdit = () => {
|
||||||
|
if (!currentBranch || !onRename) return;
|
||||||
|
setEditBranchName(currentBranch);
|
||||||
|
setIsEditing(true);
|
||||||
|
// Focus input after state update
|
||||||
|
setTimeout(() => inputRef.current?.focus(), 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveEdit = async () => {
|
||||||
|
if (!currentBranch || !onRename || !editBranchName.trim()) return;
|
||||||
|
|
||||||
|
const sanitizedName = sanitizeBranchNameInput(editBranchName);
|
||||||
|
if (sanitizedName === currentBranch) {
|
||||||
|
setIsEditing(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsRenaming(true);
|
||||||
|
try {
|
||||||
|
await onRename(currentBranch, sanitizedName);
|
||||||
|
setIsEditing(false);
|
||||||
|
setEditBranchName('');
|
||||||
|
} finally {
|
||||||
|
setIsRenaming(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancelEdit = () => {
|
||||||
|
setIsEditing(false);
|
||||||
|
setEditBranchName('');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle Enter key to save, Escape to cancel
|
||||||
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
handleSaveEdit();
|
||||||
|
} else if (e.key === 'Escape') {
|
||||||
|
e.preventDefault();
|
||||||
|
handleCancelEdit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isEditing) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-2 rounded-md bg-primary/12 px-2 py-1 h-8">
|
||||||
|
<form
|
||||||
|
className="flex w-full items-center gap-2"
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleSaveEdit();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RiGitBranchLine className="size-4 text-primary" />
|
||||||
|
<input
|
||||||
|
ref={inputRef}
|
||||||
|
value={editBranchName}
|
||||||
|
onChange={(e) => setEditBranchName(e.target.value)}
|
||||||
|
className="flex-1 min-w-0 bg-transparent typography-ui-label outline-none placeholder:text-muted-foreground"
|
||||||
|
placeholder="Branch name"
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={isRenaming}
|
||||||
|
className="shrink-0 text-muted-foreground hover:text-foreground disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{isRenaming ? (
|
||||||
|
<RiLoader4Line className="size-4 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<RiCheckLine className="size-4" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleCancelEdit}
|
||||||
|
disabled={isRenaming}
|
||||||
|
className="shrink-0 text-muted-foreground hover:text-foreground disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<RiCloseLine className="size-4" />
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="flex items-center gap-1.5 px-2 py-1 h-8">
|
||||||
|
<RiGitBranchLine className="size-4 text-primary" />
|
||||||
|
<span className="max-w-[140px] truncate typography-ui-label font-normal text-foreground">
|
||||||
|
{currentBranch || 'Detached HEAD'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{onRename && currentBranch && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="h-8 w-8 p-0"
|
||||||
|
onClick={handleStartEdit}
|
||||||
|
title="Rename branch"
|
||||||
|
>
|
||||||
|
<RiEditLine className="size-4" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -281,6 +281,7 @@ export interface GitAPI {
|
|||||||
gitFetch(directory: string, options?: { remote?: string; branch?: string }): Promise<{ success: boolean }>;
|
gitFetch(directory: string, options?: { remote?: string; branch?: string }): Promise<{ success: boolean }>;
|
||||||
checkoutBranch(directory: string, branch: string): Promise<{ success: boolean; branch: string }>;
|
checkoutBranch(directory: string, branch: string): Promise<{ success: boolean; branch: string }>;
|
||||||
createBranch(directory: string, name: string, startPoint?: string): Promise<{ success: boolean; branch: string }>;
|
createBranch(directory: string, name: string, startPoint?: string): Promise<{ success: boolean; branch: string }>;
|
||||||
|
renameBranch(directory: string, oldName: string, newName: string): Promise<{ success: boolean; branch: string }>;
|
||||||
getGitLog(directory: string, options?: GitLogOptions): Promise<GitLogResponse>;
|
getGitLog(directory: string, options?: GitLogOptions): Promise<GitLogResponse>;
|
||||||
getCommitFiles(directory: string, hash: string): Promise<GitCommitFilesResponse>;
|
getCommitFiles(directory: string, hash: string): Promise<GitCommitFilesResponse>;
|
||||||
getCurrentGitIdentity(directory: string): Promise<GitIdentitySummary | null>;
|
getCurrentGitIdentity(directory: string): Promise<GitIdentitySummary | null>;
|
||||||
|
|||||||
@@ -179,6 +179,16 @@ export async function createBranch(
|
|||||||
return gitHttp.createBranch(directory, name, startPoint);
|
return gitHttp.createBranch(directory, name, startPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function renameBranch(
|
||||||
|
directory: string,
|
||||||
|
oldName: string,
|
||||||
|
newName: string
|
||||||
|
): Promise<{ success: boolean; branch: string }> {
|
||||||
|
const runtime = getRuntimeGit();
|
||||||
|
if (runtime) return runtime.renameBranch(directory, oldName, newName);
|
||||||
|
return gitHttp.renameBranch(directory, oldName, newName);
|
||||||
|
}
|
||||||
|
|
||||||
export async function getGitLog(
|
export async function getGitLog(
|
||||||
directory: string,
|
directory: string,
|
||||||
options: import('./api/types').GitLogOptions = {}
|
options: import('./api/types').GitLogOptions = {}
|
||||||
|
|||||||
@@ -404,6 +404,23 @@ export async function createBranch(
|
|||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function renameBranch(
|
||||||
|
directory: string,
|
||||||
|
oldName: string,
|
||||||
|
newName: string
|
||||||
|
): Promise<{ success: boolean; branch: string }> {
|
||||||
|
const response = await fetch(buildUrl(`${API_BASE}/branches/rename`, directory), {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ oldName, newName }),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json().catch(() => ({ error: response.statusText }));
|
||||||
|
throw new Error(error.error || 'Failed to rename branch');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
export async function getGitLog(
|
export async function getGitLog(
|
||||||
directory: string,
|
directory: string,
|
||||||
options: GitLogOptions = {}
|
options: GitLogOptions = {}
|
||||||
|
|||||||
@@ -174,6 +174,15 @@ export const createVSCodeGitAPI = (): GitAPI => ({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renameBranch: async (directory: string, oldName: string, newName: string): Promise<{ success: boolean; branch: string }> => {
|
||||||
|
return sendBridgeMessage<{ success: boolean; branch: string }>('api:git/branches/rename', {
|
||||||
|
directory,
|
||||||
|
method: 'PUT',
|
||||||
|
oldName,
|
||||||
|
newName,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
getGitLog: async (directory: string, options?: GitLogOptions): Promise<GitLogResponse> => {
|
getGitLog: async (directory: string, options?: GitLogOptions): Promise<GitLogResponse> => {
|
||||||
return sendBridgeMessage<GitLogResponse>('api:git/log', {
|
return sendBridgeMessage<GitLogResponse>('api:git/log', {
|
||||||
directory,
|
directory,
|
||||||
|
|||||||
@@ -3818,6 +3818,30 @@ async function main(options = {}) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
app.put('/api/git/branches/rename', async (req, res) => {
|
||||||
|
const { renameBranch } = await getGitLibraries();
|
||||||
|
try {
|
||||||
|
const directory = req.query.directory;
|
||||||
|
if (!directory) {
|
||||||
|
return res.status(400).json({ error: 'directory parameter is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { oldName, newName } = req.body;
|
||||||
|
if (!oldName) {
|
||||||
|
return res.status(400).json({ error: 'oldName is required' });
|
||||||
|
}
|
||||||
|
if (!newName) {
|
||||||
|
return res.status(400).json({ error: 'newName is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await renameBranch(directory, oldName, newName);
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to rename branch:', error);
|
||||||
|
res.status(500).json({ error: error.message || 'Failed to rename branch' });
|
||||||
|
}
|
||||||
|
});
|
||||||
app.delete('/api/git/remote-branches', async (req, res) => {
|
app.delete('/api/git/remote-branches', async (req, res) => {
|
||||||
const { deleteRemoteBranch } = await getGitLibraries();
|
const { deleteRemoteBranch } = await getGitLibraries();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -29,6 +29,22 @@ const normalizeDirectoryPath = (value) => {
|
|||||||
return trimmed;
|
return trimmed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cleanBranchName = (branch) => {
|
||||||
|
if (!branch) {
|
||||||
|
return branch;
|
||||||
|
}
|
||||||
|
if (branch.startsWith('refs/heads/')) {
|
||||||
|
return branch.substring('refs/heads/'.length);
|
||||||
|
}
|
||||||
|
if (branch.startsWith('heads/')) {
|
||||||
|
return branch.substring('heads/'.length);
|
||||||
|
}
|
||||||
|
if (branch.startsWith('refs/')) {
|
||||||
|
return branch.substring('refs/'.length);
|
||||||
|
}
|
||||||
|
return branch;
|
||||||
|
};
|
||||||
|
|
||||||
export async function isGitRepository(directory) {
|
export async function isGitRepository(directory) {
|
||||||
const directoryPath = normalizeDirectoryPath(directory);
|
const directoryPath = normalizeDirectoryPath(directory);
|
||||||
if (!directoryPath || !fs.existsSync(directoryPath)) {
|
if (!directoryPath || !fs.existsSync(directoryPath)) {
|
||||||
@@ -805,7 +821,7 @@ export async function getWorktrees(directory) {
|
|||||||
} else if (line.startsWith('HEAD ')) {
|
} else if (line.startsWith('HEAD ')) {
|
||||||
current.head = line.substring(5);
|
current.head = line.substring(5);
|
||||||
} else if (line.startsWith('branch ')) {
|
} else if (line.startsWith('branch ')) {
|
||||||
current.branch = line.substring(7);
|
current.branch = cleanBranchName(line.substring(7));
|
||||||
} else if (line === '') {
|
} else if (line === '') {
|
||||||
if (current.worktree) {
|
if (current.worktree) {
|
||||||
worktrees.push(current);
|
worktrees.push(current);
|
||||||
@@ -1086,3 +1102,16 @@ export async function getCommitFiles(directory, commitHash) {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function renameBranch(directory, oldName, newName) {
|
||||||
|
const git = simpleGit(normalizeDirectoryPath(directory));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Use git branch -m command to rename the branch
|
||||||
|
await git.raw(['branch', '-m', oldName, newName]);
|
||||||
|
return { success: true, branch: newName };
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to rename branch:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export const createWebGitAPI = (): GitAPI => ({
|
|||||||
gitFetch: gitApiHttp.gitFetch,
|
gitFetch: gitApiHttp.gitFetch,
|
||||||
checkoutBranch: gitApiHttp.checkoutBranch,
|
checkoutBranch: gitApiHttp.checkoutBranch,
|
||||||
createBranch: gitApiHttp.createBranch,
|
createBranch: gitApiHttp.createBranch,
|
||||||
|
renameBranch: gitApiHttp.renameBranch,
|
||||||
getGitLog(directory: string, options?: GitLogOptions) {
|
getGitLog(directory: string, options?: GitLogOptions) {
|
||||||
return gitApiHttp.getGitLog(directory, options);
|
return gitApiHttp.getGitLog(directory, options);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user