删除分支时,如果提示分支未合并完成,支持强制删除,而不是永远无法删除

This commit is contained in:
xintaofei
2026-03-15 18:44:20 +08:00
parent 157fa2b77f
commit 31a4fd5b4b
11 changed files with 58 additions and 14 deletions

View File

@@ -100,7 +100,7 @@ interface BranchDropdownProps {
} }
type ConfirmAction = { type ConfirmAction = {
type: "merge" | "rebase" | "delete" type: "merge" | "rebase" | "delete" | "forceDelete"
branchName: string branchName: string
} }
@@ -189,7 +189,8 @@ export function BranchDropdown({
async function runGitTask<T>( async function runGitTask<T>(
label: string, label: string,
action: () => Promise<T>, action: () => Promise<T>,
getSuccessDescription?: (result: T) => string | false | undefined getSuccessDescription?: (result: T) => string | false | undefined,
onError?: (errorMsg: string) => boolean
) { ) {
const taskId = `git-${++taskSeq.current}-${Date.now()}` const taskId = `git-${++taskSeq.current}-${Date.now()}`
setLoading(true) setLoading(true)
@@ -212,8 +213,11 @@ export function BranchDropdown({
} }
} catch (err) { } catch (err) {
removeTask(taskId) removeTask(taskId)
const errorTitle = t("toasts.taskFailed", { label })
const errorMsg = toErrorMessage(err) const errorMsg = toErrorMessage(err)
if (onError?.(errorMsg)) {
return
}
const errorTitle = t("toasts.taskFailed", { label })
pushAlert("error", errorTitle, errorMsg) pushAlert("error", errorTitle, errorMsg)
toast.error(errorTitle, { description: errorMsg }) toast.error(errorTitle, { description: errorMsg })
} finally { } finally {
@@ -472,8 +476,22 @@ export function BranchDropdown({
) )
break break
case "delete": case "delete":
await runGitTask(
t("tasks.deleteBranch", { branchName }),
() => gitDeleteBranch(folderPath, branchName),
undefined,
(errorMsg) => {
if (/not fully merged/i.test(errorMsg)) {
setConfirmAction({ type: "forceDelete", branchName })
return true
}
return false
}
)
break
case "forceDelete":
await runGitTask(t("tasks.deleteBranch", { branchName }), () => await runGitTask(t("tasks.deleteBranch", { branchName }), () =>
gitDeleteBranch(folderPath, branchName) gitDeleteBranch(folderPath, branchName, true)
) )
break break
} }
@@ -488,6 +506,8 @@ export function BranchDropdown({
return t("confirm.rebaseTitle") return t("confirm.rebaseTitle")
case "delete": case "delete":
return t("confirm.deleteTitle") return t("confirm.deleteTitle")
case "forceDelete":
return t("confirm.forceDeleteTitle")
} }
} }
@@ -508,6 +528,10 @@ export function BranchDropdown({
return t("confirm.deleteDescription", { return t("confirm.deleteDescription", {
branchName: confirmAction.branchName, branchName: confirmAction.branchName,
}) })
case "forceDelete":
return t("confirm.forceDeleteDescription", {
branchName: confirmAction.branchName,
})
} }
} }

View File

@@ -810,7 +810,9 @@
"deleteTitle": "حذف الفرع", "deleteTitle": "حذف الفرع",
"mergeDescription": "دمج {branchName} في الفرع الحالي {currentBranch}؟", "mergeDescription": "دمج {branchName} في الفرع الحالي {currentBranch}؟",
"rebaseDescription": "إجراء rebase للفرع الحالي {currentBranch} على {branchName}؟", "rebaseDescription": "إجراء rebase للفرع الحالي {currentBranch} على {branchName}؟",
"deleteDescription": "حذف الفرع {branchName}؟ لا يمكن التراجع عن هذا الإجراء." "deleteDescription": "حذف الفرع {branchName}؟ لا يمكن التراجع عن هذا الإجراء.",
"forceDeleteTitle": "حذف الفرع بالقوة",
"forceDeleteDescription": "الفرع {branchName} لم يتم دمجه بالكامل. هل أنت متأكد من أنك تريد حذفه بالقوة؟ لا يمكن التراجع عن هذا الإجراء."
}, },
"current": "الحالي", "current": "الحالي",
"switchToBranch": "التبديل إلى هذا الفرع", "switchToBranch": "التبديل إلى هذا الفرع",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Branch löschen", "deleteTitle": "Branch löschen",
"mergeDescription": "{branchName} in den aktuellen Branch {currentBranch} mergen?", "mergeDescription": "{branchName} in den aktuellen Branch {currentBranch} mergen?",
"rebaseDescription": "Aktuellen Branch {currentBranch} auf {branchName} rebasen?", "rebaseDescription": "Aktuellen Branch {currentBranch} auf {branchName} rebasen?",
"deleteDescription": "Branch {branchName} löschen? Diese Aktion kann nicht rückgängig gemacht werden." "deleteDescription": "Branch {branchName} löschen? Diese Aktion kann nicht rückgängig gemacht werden.",
"forceDeleteTitle": "Branch erzwungen löschen",
"forceDeleteDescription": "Der Branch {branchName} ist nicht vollständig gemergt. Möchten Sie ihn wirklich erzwungen löschen? Diese Aktion kann nicht rückgängig gemacht werden."
}, },
"current": "Aktuell", "current": "Aktuell",
"switchToBranch": "Zu diesem Branch wechseln", "switchToBranch": "Zu diesem Branch wechseln",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Delete branch", "deleteTitle": "Delete branch",
"mergeDescription": "Merge {branchName} into current branch {currentBranch}?", "mergeDescription": "Merge {branchName} into current branch {currentBranch}?",
"rebaseDescription": "Rebase current branch {currentBranch} onto {branchName}?", "rebaseDescription": "Rebase current branch {currentBranch} onto {branchName}?",
"deleteDescription": "Delete branch {branchName}? This action cannot be undone." "deleteDescription": "Delete branch {branchName}? This action cannot be undone.",
"forceDeleteTitle": "Force Delete Branch",
"forceDeleteDescription": "Branch {branchName} is not fully merged. Are you sure you want to force delete it? This action cannot be undone."
}, },
"current": "Current", "current": "Current",
"switchToBranch": "Switch to this branch", "switchToBranch": "Switch to this branch",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Eliminar rama", "deleteTitle": "Eliminar rama",
"mergeDescription": "¿Fusionar {branchName} en la rama actual {currentBranch}?", "mergeDescription": "¿Fusionar {branchName} en la rama actual {currentBranch}?",
"rebaseDescription": "¿Hacer rebase de la rama actual {currentBranch} sobre {branchName}?", "rebaseDescription": "¿Hacer rebase de la rama actual {currentBranch} sobre {branchName}?",
"deleteDescription": "¿Eliminar la rama {branchName}? Esta acción no se puede deshacer." "deleteDescription": "¿Eliminar la rama {branchName}? Esta acción no se puede deshacer.",
"forceDeleteTitle": "Forzar eliminación de rama",
"forceDeleteDescription": "La rama {branchName} no está completamente fusionada. ¿Estás seguro de que quieres forzar su eliminación? Esta acción no se puede deshacer."
}, },
"current": "Actual", "current": "Actual",
"switchToBranch": "Cambiar a esta rama", "switchToBranch": "Cambiar a esta rama",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Supprimer la branche", "deleteTitle": "Supprimer la branche",
"mergeDescription": "Fusionner {branchName} dans la branche actuelle {currentBranch} ?", "mergeDescription": "Fusionner {branchName} dans la branche actuelle {currentBranch} ?",
"rebaseDescription": "Rebaser la branche actuelle {currentBranch} sur {branchName} ?", "rebaseDescription": "Rebaser la branche actuelle {currentBranch} sur {branchName} ?",
"deleteDescription": "Supprimer la branche {branchName} ? Cette action est irréversible." "deleteDescription": "Supprimer la branche {branchName} ? Cette action est irréversible.",
"forceDeleteTitle": "Forcer la suppression de la branche",
"forceDeleteDescription": "La branche {branchName} n'est pas entièrement fusionnée. Êtes-vous sûr de vouloir la supprimer de force ? Cette action est irréversible."
}, },
"current": "Actuelle", "current": "Actuelle",
"switchToBranch": "Basculer vers cette branche", "switchToBranch": "Basculer vers cette branche",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "ブランチを削除", "deleteTitle": "ブランチを削除",
"mergeDescription": "{branchName} を現在のブランチ {currentBranch} にマージしますか?", "mergeDescription": "{branchName} を現在のブランチ {currentBranch} にマージしますか?",
"rebaseDescription": "現在のブランチ {currentBranch} を {branchName} にリベースしますか?", "rebaseDescription": "現在のブランチ {currentBranch} を {branchName} にリベースしますか?",
"deleteDescription": "ブランチ {branchName} を削除しますか?この操作は元に戻せません。" "deleteDescription": "ブランチ {branchName} を削除しますか?この操作は元に戻せません。",
"forceDeleteTitle": "ブランチを強制削除",
"forceDeleteDescription": "ブランチ {branchName} はまだ完全にマージされていません。強制削除してもよろしいですか?この操作は元に戻せません。"
}, },
"current": "現在", "current": "現在",
"switchToBranch": "このブランチに切り替え", "switchToBranch": "このブランチに切り替え",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "브랜치 삭제", "deleteTitle": "브랜치 삭제",
"mergeDescription": "{branchName}을(를) 현재 브랜치 {currentBranch}에 병합할까요?", "mergeDescription": "{branchName}을(를) 현재 브랜치 {currentBranch}에 병합할까요?",
"rebaseDescription": "현재 브랜치 {currentBranch}를 {branchName} 위로 리베이스할까요?", "rebaseDescription": "현재 브랜치 {currentBranch}를 {branchName} 위로 리베이스할까요?",
"deleteDescription": "브랜치 {branchName}을(를) 삭제할까요? 이 작업은 되돌릴 수 없습니다." "deleteDescription": "브랜치 {branchName}을(를) 삭제할까요? 이 작업은 되돌릴 수 없습니다.",
"forceDeleteTitle": "브랜치 강제 삭제",
"forceDeleteDescription": "브랜치 {branchName}가 완전히 병합되지 않았습니다. 강제 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다."
}, },
"current": "현재", "current": "현재",
"switchToBranch": "이 브랜치로 전환", "switchToBranch": "이 브랜치로 전환",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Excluir branch", "deleteTitle": "Excluir branch",
"mergeDescription": "Mesclar {branchName} na branch atual {currentBranch}?", "mergeDescription": "Mesclar {branchName} na branch atual {currentBranch}?",
"rebaseDescription": "Fazer rebase da branch atual {currentBranch} sobre {branchName}?", "rebaseDescription": "Fazer rebase da branch atual {currentBranch} sobre {branchName}?",
"deleteDescription": "Excluir a branch {branchName}? Esta ação não pode ser desfeita." "deleteDescription": "Excluir a branch {branchName}? Esta ação não pode ser desfeita.",
"forceDeleteTitle": "Forçar exclusão do branch",
"forceDeleteDescription": "O branch {branchName} não está totalmente mesclado. Tem certeza de que deseja forçar a exclusão? Esta ação não pode ser desfeita."
}, },
"current": "Atual", "current": "Atual",
"switchToBranch": "Mudar para esta branch", "switchToBranch": "Mudar para esta branch",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "删除分支", "deleteTitle": "删除分支",
"mergeDescription": "确定将 {branchName} 合并到当前分支 {currentBranch} 吗?", "mergeDescription": "确定将 {branchName} 合并到当前分支 {currentBranch} 吗?",
"rebaseDescription": "确定将当前分支 {currentBranch} 变基到 {branchName} 吗?", "rebaseDescription": "确定将当前分支 {currentBranch} 变基到 {branchName} 吗?",
"deleteDescription": "确定删除分支 {branchName} 吗?此操作不可恢复。" "deleteDescription": "确定删除分支 {branchName} 吗?此操作不可恢复。",
"forceDeleteTitle": "强制删除分支",
"forceDeleteDescription": "分支 {branchName} 尚未完全合并,确定要强制删除吗?此操作不可恢复。"
}, },
"current": "当前", "current": "当前",
"switchToBranch": "切换到此分支", "switchToBranch": "切换到此分支",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "刪除分支", "deleteTitle": "刪除分支",
"mergeDescription": "確定將 {branchName} 合併到目前分支 {currentBranch} 嗎?", "mergeDescription": "確定將 {branchName} 合併到目前分支 {currentBranch} 嗎?",
"rebaseDescription": "確定將目前分支 {currentBranch} 變基到 {branchName} 嗎?", "rebaseDescription": "確定將目前分支 {currentBranch} 變基到 {branchName} 嗎?",
"deleteDescription": "確定刪除分支 {branchName} 嗎?此操作無法復原。" "deleteDescription": "確定刪除分支 {branchName} 嗎?此操作無法復原。",
"forceDeleteTitle": "強制刪除分支",
"forceDeleteDescription": "分支 {branchName} 尚未完全合併,確定要強制刪除嗎?此操作不可恢復。"
}, },
"current": "目前", "current": "目前",
"switchToBranch": "切換到此分支", "switchToBranch": "切換到此分支",