Skip to content

Commit 5eb6daf

Browse files
committed
Show a warning popup when undoing a pushed commit
1 parent 5387e40 commit 5eb6daf

4 files changed

Lines changed: 112 additions & 1 deletion

File tree

app/src/lib/stores/app-store.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5641,10 +5641,22 @@ export class AppStore extends TypedBaseStore<IAppState> {
56415641
): Promise<void> {
56425642
const gitStore = this.gitStoreCache.get(repository)
56435643
const repositoryState = this.repositoryStateCache.get(repository)
5644-
const { changesState } = repositoryState
5644+
const { changesState, localCommitSHAs } = repositoryState
56455645
const isWorkingDirectoryClean =
56465646
changesState.workingDirectory.files.length === 0
56475647

5648+
// Check if the commit has been pushed (not a local commit)
5649+
const isPushedCommit = !localCommitSHAs.includes(commit.sha)
5650+
5651+
// Warn the user if they're undoing a pushed commit
5652+
if (showConfirmationDialog && isPushedCommit) {
5653+
return this._showPopup({
5654+
type: PopupType.WarnUndoPushedCommit,
5655+
repository,
5656+
commit,
5657+
})
5658+
}
5659+
56485660
// Warn the user if there are changes in the working directory
56495661
// This warning can be disabled, except when the user tries to undo
56505662
// a merge commit.

app/src/models/popup.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export enum PopupType {
8282
CommitMessage = 'CommitMessage',
8383
MultiCommitOperation = 'MultiCommitOperation',
8484
WarnLocalChangesBeforeUndo = 'WarnLocalChangesBeforeUndo',
85+
WarnUndoPushedCommit = 'WarnUndoPushedCommit',
8586
WarningBeforeReset = 'WarningBeforeReset',
8687
InvalidatedToken = 'InvalidatedToken',
8788
AddSSHHost = 'AddSSHHost',
@@ -342,6 +343,11 @@ export type PopupDetail =
342343
commit: Commit
343344
isWorkingDirectoryClean: boolean
344345
}
346+
| {
347+
type: PopupType.WarnUndoPushedCommit
348+
repository: Repository
349+
commit: Commit
350+
}
345351
| {
346352
type: PopupType.WarningBeforeReset
347353
repository: Repository

app/src/ui/app.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ import { DragType, DropTargetSelector } from '../models/drag-drop'
145145
import { dragAndDropManager } from '../lib/drag-and-drop-manager'
146146
import { MultiCommitOperation } from './multi-commit-operation/multi-commit-operation'
147147
import { WarnLocalChangesBeforeUndo } from './undo/warn-local-changes-before-undo'
148+
import { WarnUndoPushedCommit } from './undo/warn-undo-pushed-commit'
148149
import { WarningBeforeReset } from './reset/warning-before-reset'
149150
import { InvalidatedToken } from './invalidated-token/invalidated-token'
150151
import { MultiCommitOperationKind } from '../models/multi-commit-operation'
@@ -2286,6 +2287,18 @@ export class App extends React.Component<IAppProps, IAppState> {
22862287
/>
22872288
)
22882289
}
2290+
case PopupType.WarnUndoPushedCommit: {
2291+
const { repository, commit } = popup
2292+
return (
2293+
<WarnUndoPushedCommit
2294+
key="warn-undo-pushed-commit"
2295+
dispatcher={this.props.dispatcher}
2296+
repository={repository}
2297+
commit={commit}
2298+
onDismissed={onPopupDismissedFn}
2299+
/>
2300+
)
2301+
}
22892302
case PopupType.WarningBeforeReset: {
22902303
const { repository, commit } = popup
22912304
return (
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import * as React from 'react'
2+
import { Dialog, DialogContent, DialogFooter } from '../dialog'
3+
import { Repository } from '../../models/repository'
4+
import { Dispatcher } from '../dispatcher'
5+
import { OkCancelButtonGroup } from '../dialog/ok-cancel-button-group'
6+
import { Commit } from '../../models/commit'
7+
8+
interface IWarnUndoPushedCommitProps {
9+
readonly dispatcher: Dispatcher
10+
readonly repository: Repository
11+
readonly commit: Commit
12+
readonly onDismissed: () => void
13+
}
14+
15+
interface IWarnUndoPushedCommitState {
16+
readonly isLoading: boolean
17+
}
18+
19+
/**
20+
* Dialog that warns user that they are about to undo a commit that has already
21+
* been pushed to the remote repository.
22+
*/
23+
export class WarnUndoPushedCommit extends React.Component<
24+
IWarnUndoPushedCommitProps,
25+
IWarnUndoPushedCommitState
26+
> {
27+
public constructor(props: IWarnUndoPushedCommitProps) {
28+
super(props)
29+
this.state = {
30+
isLoading: false,
31+
}
32+
}
33+
34+
public render() {
35+
const title = __DARWIN__ ? 'Undo Pushed Commit?' : 'Undo pushed commit?'
36+
37+
return (
38+
<Dialog
39+
id="warn-undo-pushed-commit"
40+
type="warning"
41+
title={title}
42+
loading={this.state.isLoading}
43+
disabled={this.state.isLoading}
44+
onSubmit={this.onSubmit}
45+
onDismissed={this.props.onDismissed}
46+
role="alertdialog"
47+
ariaDescribedBy="undo-pushed-commit-warning-message"
48+
>
49+
<DialogContent>
50+
<p id="undo-pushed-commit-warning-message">
51+
This commit has already been pushed to the remote repository.
52+
Undoing it will rewrite your local history.
53+
</p>
54+
<p>
55+
If others have pulled this commit, they may encounter issues when
56+
pushing or pulling. You will need to force push to update the remote
57+
repository.
58+
</p>
59+
<p>Are you sure you want to continue?</p>
60+
</DialogContent>
61+
<DialogFooter>
62+
<OkCancelButtonGroup destructive={true} okButtonText="Undo Commit" />
63+
</DialogFooter>
64+
</Dialog>
65+
)
66+
}
67+
68+
private onSubmit = async () => {
69+
const { dispatcher, repository, commit, onDismissed } = this.props
70+
this.setState({ isLoading: true })
71+
72+
try {
73+
await dispatcher.undoCommit(repository, commit, false)
74+
} finally {
75+
this.setState({ isLoading: false })
76+
}
77+
78+
onDismissed()
79+
}
80+
}

0 commit comments

Comments
 (0)