diff --git a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
index e618fb3daaebe250e06af68e22b30846a39ffa40..24499fb9f6d19ab71d50de472b3dfcfe6dae944e 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
@@ -24,8 +24,8 @@ export default {
     discardModalTitle() {
       return sprintf(__('Discard changes to %{path}?'), { path: this.activeFile.path });
     },
-    isStaged() {
-      return !this.activeFile.changed && this.activeFile.staged;
+    canDiscard() {
+      return this.activeFile.changed || this.activeFile.staged;
     },
   },
   methods: {
@@ -53,7 +53,7 @@ export default {
     <changed-file-icon :file="activeFile" :is-centered="false" />
     <div class="ml-auto">
       <button
-        v-if="!isStaged"
+        v-if="canDiscard"
         ref="discardButton"
         type="button"
         class="btn btn-remove btn-inverted append-right-8"
diff --git a/changelogs/unreleased/213238-fix-ide-discard-empty-file.yml b/changelogs/unreleased/213238-fix-ide-discard-empty-file.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1a8ac3400c577b40bcd98d3c8b89fc2f6183a8fc
--- /dev/null
+++ b/changelogs/unreleased/213238-fix-ide-discard-empty-file.yml
@@ -0,0 +1,5 @@
+---
+title: Fix discard button not showing for new empty files in Web IDE
+merge_request: 30767
+author:
+type: fixed
diff --git a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
index a25aba615169897a3b91673eecf559e6690d03db..ff780939026ed09ef13e7331e3205fc7e2111ecc 100644
--- a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
@@ -7,27 +7,32 @@ import { file } from '../../helpers';
 const localVue = createLocalVue();
 localVue.use(Vuex);
 
+const TEST_FILE_PATH = 'test/file/path';
+
 describe('IDE commit editor header', () => {
   let wrapper;
-  let f;
   let store;
 
-  const findDiscardModal = () => wrapper.find({ ref: 'discardModal' });
-  const findDiscardButton = () => wrapper.find({ ref: 'discardButton' });
-
-  beforeEach(() => {
-    f = file('file');
-    store = createStore();
-
+  const createComponent = (fileProps = {}) => {
     wrapper = mount(EditorHeader, {
       store,
       localVue,
       propsData: {
-        activeFile: f,
+        activeFile: {
+          ...file(TEST_FILE_PATH),
+          staged: true,
+          ...fileProps,
+        },
       },
     });
+  };
 
-    jest.spyOn(wrapper.vm, 'discardChanges').mockImplementation();
+  const findDiscardModal = () => wrapper.find({ ref: 'discardModal' });
+  const findDiscardButton = () => wrapper.find({ ref: 'discardButton' });
+
+  beforeEach(() => {
+    store = createStore();
+    jest.spyOn(store, 'dispatch').mockImplementation();
   });
 
   afterEach(() => {
@@ -35,29 +40,38 @@ describe('IDE commit editor header', () => {
     wrapper = null;
   });
 
-  it('renders button to discard', () => {
-    expect(wrapper.vm.$el.querySelectorAll('.btn')).toHaveLength(1);
+  it.each`
+    fileProps                            | shouldExist
+    ${{ staged: false, changed: false }} | ${false}
+    ${{ staged: true, changed: false }}  | ${true}
+    ${{ staged: false, changed: true }}  | ${true}
+    ${{ staged: true, changed: true }}   | ${true}
+  `('with $fileProps, show discard button is $shouldExist', ({ fileProps, shouldExist }) => {
+    createComponent(fileProps);
+
+    expect(findDiscardButton().exists()).toBe(shouldExist);
   });
 
   describe('discard button', () => {
-    let modal;
-
     beforeEach(() => {
-      modal = findDiscardModal();
+      createComponent();
 
+      const modal = findDiscardModal();
       jest.spyOn(modal.vm, 'show');
 
       findDiscardButton().trigger('click');
     });
 
     it('opens a dialog confirming discard', () => {
-      expect(modal.vm.show).toHaveBeenCalled();
+      expect(findDiscardModal().vm.show).toHaveBeenCalled();
     });
 
     it('calls discardFileChanges if dialog result is confirmed', () => {
-      modal.vm.$emit('ok');
+      expect(store.dispatch).not.toHaveBeenCalled();
+
+      findDiscardModal().vm.$emit('ok');
 
-      expect(wrapper.vm.discardChanges).toHaveBeenCalledWith(f.path);
+      expect(store.dispatch).toHaveBeenCalledWith('discardFileChanges', TEST_FILE_PATH);
     });
   });
 });