From 8540f5139580e9aaa278597c994ffb28bed33567 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Wed, 6 May 2026 00:12:39 +0300 Subject: [PATCH] fix: make commit sync use safe sync flow Rename commit push action to Commit & sync Use fetch and rebase before pushing committed changes Keep sync result toasts consistent --- packages/ui/src/components/views/GitView.tsx | 51 +++++++++++++++++++- packages/ui/src/lib/i18n/messages/en.ts | 6 +-- packages/ui/src/lib/i18n/messages/es.ts | 6 +-- packages/ui/src/lib/i18n/messages/ko.ts | 6 +-- packages/ui/src/lib/i18n/messages/pt-BR.ts | 6 +-- packages/ui/src/lib/i18n/messages/uk.ts | 6 +-- packages/ui/src/lib/i18n/messages/zh-CN.ts | 6 +-- 7 files changed, 67 insertions(+), 20 deletions(-) diff --git a/packages/ui/src/components/views/GitView.tsx b/packages/ui/src/components/views/GitView.tsx index a5dcfc66..d7901618 100644 --- a/packages/ui/src/components/views/GitView.tsx +++ b/packages/ui/src/components/views/GitView.tsx @@ -1057,8 +1057,55 @@ export const GitView: React.FC = () => { await refreshStatusAndBranches(); if (options.pushAfter) { - await git.gitPush(currentDirectory); - toast.success(t('gitView.toast.pushedToUpstream')); + const trackingRemoteName = status?.tracking?.split('/')[0]; + const syncRemote = effectiveRemotes.find((remote) => remote.name === trackingRemoteName) ?? effectiveRemotes[0]; + if (!syncRemote) { + throw new Error('No remote available for sync'); + } + + const trackingPrefix = `${syncRemote.name}/`; + const trackedBranch = status?.tracking?.startsWith(trackingPrefix) + ? status.tracking.slice(trackingPrefix.length) + : undefined; + let pulledFileCount = 0; + let pushedChanges = false; + + await git.gitFetch(currentDirectory, { remote: syncRemote.name }); + const afterFetch = await git.getGitStatus(currentDirectory); + + if ((afterFetch.behind ?? 0) > 0) { + const pullResult = await git.gitPull(currentDirectory, { + remote: syncRemote.name, + branch: trackedBranch, + rebase: true, + }); + pulledFileCount = pullResult.files.length; + } + + const afterPull = await git.getGitStatus(currentDirectory); + if ((afterPull.ahead ?? 0) > 0) { + await git.gitPush(currentDirectory); + pushedChanges = true; + } + + if (pulledFileCount > 0 && pushedChanges) { + toast.success( + pulledFileCount === 1 + ? t('gitView.toast.syncedPulledSingleAndPushed', { count: pulledFileCount, name: syncRemote.name }) + : t('gitView.toast.syncedPulledPluralAndPushed', { count: pulledFileCount, name: syncRemote.name }) + ); + } else if (pulledFileCount > 0) { + toast.success( + pulledFileCount === 1 + ? t('gitView.toast.pulledFilesSingle', { count: pulledFileCount, name: syncRemote.name }) + : t('gitView.toast.pulledFilesPlural', { count: pulledFileCount, name: syncRemote.name }) + ); + } else if (pushedChanges) { + toast.success(t('gitView.toast.pushedToUpstream')); + } else { + toast.success(t('gitView.toast.syncedChanges')); + } + triggerFireworks(); await refreshStatusAndBranches(false); } else { diff --git a/packages/ui/src/lib/i18n/messages/en.ts b/packages/ui/src/lib/i18n/messages/en.ts index 6ff7c0ec..01620f58 100644 --- a/packages/ui/src/lib/i18n/messages/en.ts +++ b/packages/ui/src/lib/i18n/messages/en.ts @@ -424,9 +424,9 @@ export const dict = { 'gitView.commit.generate': 'Generate', 'gitView.commit.generateAria': 'Generate commit message', 'gitView.commit.messagePlaceholder': 'Commit message', - 'gitView.commit.push': 'Push', - 'gitView.commit.pushAria': 'Push', - 'gitView.commit.pushing': 'Pushing...', + 'gitView.commit.push': 'Commit & sync', + 'gitView.commit.pushAria': 'Commit and sync', + 'gitView.commit.pushing': 'Syncing...', 'gitView.commit.selectFilesHint': 'Select files in Changes to enable commit.', 'gitView.commit.title': 'Commit', 'gitView.common.cancel': 'Cancel', diff --git a/packages/ui/src/lib/i18n/messages/es.ts b/packages/ui/src/lib/i18n/messages/es.ts index 147de2cd..818d619c 100644 --- a/packages/ui/src/lib/i18n/messages/es.ts +++ b/packages/ui/src/lib/i18n/messages/es.ts @@ -425,9 +425,9 @@ export const dict: Record = { "gitView.commit.generate": "Generar", "gitView.commit.generateAria": "Generar mensaje de commit", "gitView.commit.messagePlaceholder": "Mensaje de commit", - "gitView.commit.push": "Push", - "gitView.commit.pushAria": "Push", - "gitView.commit.pushing": "Enviando...", + "gitView.commit.push": "Commit & sync", + "gitView.commit.pushAria": "Commit and sync", + "gitView.commit.pushing": "Sincronizando...", "gitView.commit.selectFilesHint": "Selecciona archivos en Cambios para habilitar el commit.", "gitView.commit.title": "Commit", "gitView.common.cancel": "Cancelar", diff --git a/packages/ui/src/lib/i18n/messages/ko.ts b/packages/ui/src/lib/i18n/messages/ko.ts index 5c3a087a..6ab668f0 100644 --- a/packages/ui/src/lib/i18n/messages/ko.ts +++ b/packages/ui/src/lib/i18n/messages/ko.ts @@ -425,9 +425,9 @@ export const dict: Record = { 'gitView.commit.generate': '생성', 'gitView.commit.generateAria': '커밋 메시지 생성', 'gitView.commit.messagePlaceholder': '커밋 메시지', - 'gitView.commit.push': '푸시', - 'gitView.commit.pushAria': '푸시', - 'gitView.commit.pushing': '푸시 중…', + 'gitView.commit.push': 'Commit & sync', + 'gitView.commit.pushAria': 'Commit and sync', + 'gitView.commit.pushing': 'sync 중…', 'gitView.commit.selectFilesHint': '커밋하려면 변경 사항에서 파일을 선택하세요.', 'gitView.commit.title': '커밋', 'gitView.common.cancel': '취소', diff --git a/packages/ui/src/lib/i18n/messages/pt-BR.ts b/packages/ui/src/lib/i18n/messages/pt-BR.ts index 283fcb07..9262cfc5 100644 --- a/packages/ui/src/lib/i18n/messages/pt-BR.ts +++ b/packages/ui/src/lib/i18n/messages/pt-BR.ts @@ -425,9 +425,9 @@ export const dict: Record = { "gitView.commit.generate": "Generar", "gitView.commit.generateAria": "Generar mensagem de commit", "gitView.commit.messagePlaceholder": "Mensagem de commit", - "gitView.commit.push": "Push", - "gitView.commit.pushAria": "Push", - "gitView.commit.pushing": "Enviando...", + "gitView.commit.push": "Commit & sync", + "gitView.commit.pushAria": "Commit and sync", + "gitView.commit.pushing": "Sincronizando...", "gitView.commit.selectFilesHint": "Selecione arquivos em Alterações para habilitar o commit.", "gitView.commit.title": "Commit", "gitView.common.cancel": "Cancelar", diff --git a/packages/ui/src/lib/i18n/messages/uk.ts b/packages/ui/src/lib/i18n/messages/uk.ts index 3e1cc1b9..38bc0c69 100644 --- a/packages/ui/src/lib/i18n/messages/uk.ts +++ b/packages/ui/src/lib/i18n/messages/uk.ts @@ -425,9 +425,9 @@ export const dict: Record = { "gitView.commit.generate": "Генерувати", "gitView.commit.generateAria": "Згенерувати повідомлення коміту", "gitView.commit.messagePlaceholder": "Повідомлення коміту", - "gitView.commit.push": "Push", - "gitView.commit.pushAria": "Push", - "gitView.commit.pushing": "Push...", + "gitView.commit.push": "Commit & sync", + "gitView.commit.pushAria": "Commit and sync", + "gitView.commit.pushing": "Sync...", "gitView.commit.selectFilesHint": "Виберіть файли в розділі «Зміни», щоб увімкнути коміт.", "gitView.commit.title": "Коміт", "gitView.common.cancel": "Скасувати", diff --git a/packages/ui/src/lib/i18n/messages/zh-CN.ts b/packages/ui/src/lib/i18n/messages/zh-CN.ts index 4dc0ac0e..676d7923 100644 --- a/packages/ui/src/lib/i18n/messages/zh-CN.ts +++ b/packages/ui/src/lib/i18n/messages/zh-CN.ts @@ -425,9 +425,9 @@ export const dict: Record = { 'gitView.commit.generate': '生成', 'gitView.commit.generateAria': '生成提交信息', 'gitView.commit.messagePlaceholder': '提交信息', - 'gitView.commit.push': '推送', - 'gitView.commit.pushAria': '推送', - 'gitView.commit.pushing': '推送中...', + 'gitView.commit.push': 'Commit & sync', + 'gitView.commit.pushAria': 'Commit and sync', + 'gitView.commit.pushing': 'sync 中...', 'gitView.commit.selectFilesHint': '在“更改”中选择文件以启用提交。', 'gitView.commit.title': '提交', 'gitView.common.cancel': '取消',