Change:
} return result; <ins> } export function getChangeRevertEdits(original: IModel, modified: IModel, changes: SelectedChange[]): IIdentifiedSingleEditOperation[] { sortChanges(changes); const getDeleteOperation = (change: IChange) => { const fullRange = getLinesRangeWithOneSurroundingNewline(modified, change.modifiedStartLineNumber, change.modifiedEndLineNumber); return EditOperation.delete(fullRange); }; return changes.map((change, i) => { if (isInsertion(change)) { // Delete inserted range return getDeleteOperation(change); } else if (isDeletion(change)) { // Get the original lines and insert at the deleted position const value = original.getValueInRange(getLinesRangeWithOneSurroundingNewline(original, change.originalStartLineNumber, change.originalEndLineNumber)); return EditOperation.insert(new Position(change.modifiedStartLineNumber + 1, 1), value); } else if (change.isCompletelySelected) { // If the entire change is selected, then revert the whole thing. const value = original.getValueInRange(new Range(change.originalStartLineNumber, 1, change.originalEndLineNumber + 1, 1)); return EditOperation.replace(new Range(change.modifiedStartLineNumber, 1, change.modifiedEndLineNumber + 1, 1), value); } else { // If only a portion is selected, replace with the matching lines - e.g. if lines 2-4 are selected, replace with lines 2-4 from the original model (if they exist) const copyOffset = change.modifiedStartLineNumber - change.fullModifiedStartLineNumber; const numLinesToCopy = change.modifiedEndLineNumber - change.modifiedStartLineNumber; const copyStartLine = change.originalStartLineNumber + copyOffset; const copyEndLine = Math.min(copyStartLine + numLinesToCopy, original.getLineCount()); if (copyStartLine > copyEndLine) { return getDeleteOperation(change); } // Compute the range to copy, and intersect with the full original range to validate const originalRange = new Range(change.originalStartLineNumber, 1, change.originalEndLineNumber, original.getLineMaxColumn(change.originalEndLineNumber)); const rangeToCopy = originalRange.intersectRanges( new Range(copyStartLine, 1, copyEndLine, original.getLineMaxColumn(copyEndLine))); // No intersection, so delete the added text if (!rangeToCopy) { return getDeleteOperation(change); } const value = original.getValueInRange(rangeToCopy); return EditOperation.replace(new Range(change.modifiedStartLineNumber, 1, change.modifiedEndLineNumber, modified.getLineMaxColumn(change.modifiedEndLineNumber)), value); } }); } function getLinesRangeWithOneSurroundingNewline(model: IModel, startLine: number, endLine: number): Range { let startColumn = 1; let endColumn = model.getLineMaxColumn(endLine); if (endLine < model.getLineCount()) { endLine++; endColumn = 1; } else if (startLine > 1) { startLine--; startColumn = model.getLineMaxColumn(startLine); } return new Range(startLine, startColumn, endLine, endColumn); </ins> }  No newline at end of file

Discussion:
There's probably already a feature request for this but I can't find it. I want to be able to select a change in the diff editor and revert it, same as how I can stage it. In SourceTree this is called "discard selected lines" although "revert" seems better, unless it's "discard selected changes". I'm working on a PR for this.
I think it is connected with