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

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: "merge" | "rebase" | "delete"
type: "merge" | "rebase" | "delete" | "forceDelete"
branchName: string
}
@@ -189,7 +189,8 @@ export function BranchDropdown({
async function runGitTask<T>(
label: string,
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()}`
setLoading(true)
@@ -212,8 +213,11 @@ export function BranchDropdown({
}
} catch (err) {
removeTask(taskId)
const errorTitle = t("toasts.taskFailed", { label })
const errorMsg = toErrorMessage(err)
if (onError?.(errorMsg)) {
return
}
const errorTitle = t("toasts.taskFailed", { label })
pushAlert("error", errorTitle, errorMsg)
toast.error(errorTitle, { description: errorMsg })
} finally {
@@ -472,8 +476,22 @@ export function BranchDropdown({
)
break
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 }), () =>
gitDeleteBranch(folderPath, branchName)
gitDeleteBranch(folderPath, branchName, true)
)
break
}
@@ -488,6 +506,8 @@ export function BranchDropdown({
return t("confirm.rebaseTitle")
case "delete":
return t("confirm.deleteTitle")
case "forceDelete":
return t("confirm.forceDeleteTitle")
}
}
@@ -508,6 +528,10 @@ export function BranchDropdown({
return t("confirm.deleteDescription", {
branchName: confirmAction.branchName,
})
case "forceDelete":
return t("confirm.forceDeleteDescription", {
branchName: confirmAction.branchName,
})
}
}

View File

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

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Branch löschen",
"mergeDescription": "{branchName} in den aktuellen Branch {currentBranch} mergen?",
"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",
"switchToBranch": "Zu diesem Branch wechseln",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Delete branch",
"mergeDescription": "Merge {branchName} into current branch {currentBranch}?",
"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",
"switchToBranch": "Switch to this branch",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Eliminar rama",
"mergeDescription": "¿Fusionar {branchName} en la rama actual {currentBranch}?",
"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",
"switchToBranch": "Cambiar a esta rama",

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Supprimer la branche",
"mergeDescription": "Fusionner {branchName} dans la branche actuelle {currentBranch} ?",
"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",
"switchToBranch": "Basculer vers cette branche",

View File

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

View File

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

View File

@@ -810,7 +810,9 @@
"deleteTitle": "Excluir branch",
"mergeDescription": "Mesclar {branchName} na branch atual {currentBranch}?",
"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",
"switchToBranch": "Mudar para esta branch",

View File

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

View File

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