diff --git a/pkg/commands/files.go b/pkg/commands/files.go
index 740928759..e7332dbbe 100644
--- a/pkg/commands/files.go
+++ b/pkg/commands/files.go
@@ -31,7 +31,7 @@ func (c *GitCommand) StageAll() error {
 	return c.OSCommand.RunCommand("git add -A")
 }
 
-// UnstageAll stages all files
+// UnstageAll unstages all files
 func (c *GitCommand) UnstageAll() error {
 	return c.OSCommand.RunCommand("git reset")
 }
diff --git a/pkg/commands/models/status_line_node.go b/pkg/commands/models/status_line_node.go
index e0a9051e2..ce85cfec8 100644
--- a/pkg/commands/models/status_line_node.go
+++ b/pkg/commands/models/status_line_node.go
@@ -144,13 +144,19 @@ func (s *StatusLineNode) sortChildren() {
 	s.Children = sortedChildren
 }
 
+// returns true if any descendant file is tracked
 func (s *StatusLineNode) GetIsTracked() bool {
 	if s.File != nil {
 		return s.File.GetIsTracked()
 	}
 
-	// pretty sure I'm allowed to do this
-	return true
+	for _, child := range s.Children {
+		if child.GetIsTracked() {
+			return true
+		}
+	}
+
+	return false
 }
 
 func (s *StatusLineNode) GetPath() string {
@@ -211,3 +217,19 @@ func (s *StatusLineNode) ID() string {
 func (s *StatusLineNode) Description() string {
 	return s.GetPath()
 }
+
+func (s *StatusLineNode) ForEachFile(cb func(*File) error) error {
+	if s.File != nil {
+		if err := cb(s.File); err != nil {
+			return err
+		}
+	}
+
+	for _, child := range s.Children {
+		if err := child.ForEachFile(cb); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go
index 772b05cf3..30ce0a51f 100644
--- a/pkg/gui/files_panel.go
+++ b/pkg/gui/files_panel.go
@@ -294,24 +294,43 @@ func (gui *Gui) handleStageAll(g *gocui.Gui, v *gocui.View) error {
 	return gui.selectFile(false)
 }
 
-func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
-	file := gui.getSelectedFile()
-	if file == nil {
+func (gui *Gui) handleIgnoreFile() error {
+	node := gui.getSelectedStatusNode()
+	if node == nil {
 		return nil
 	}
-	if file.Name == ".gitignore" {
+
+	if node.GetPath() == ".gitignore" {
 		return gui.createErrorPanel("Cannot ignore .gitignore")
 	}
 
-	if file.Tracked {
+	unstageFiles := func() error {
+		return node.ForEachFile(func(file *models.File) error {
+			if file.HasStagedChanges {
+				if err := gui.GitCommand.UnStageFile(file.Name, file.Tracked); err != nil {
+					return err
+				}
+			}
+
+			return nil
+		})
+	}
+
+	if node.GetIsTracked() {
 		return gui.ask(askOpts{
 			title:  gui.Tr.IgnoreTracked,
 			prompt: gui.Tr.IgnoreTrackedPrompt,
 			handleConfirm: func() error {
-				if err := gui.GitCommand.Ignore(file.Name); err != nil {
+				// not 100% sure if this is necessary but I'll assume it is
+				if err := unstageFiles(); err != nil {
 					return err
 				}
-				if err := gui.GitCommand.RemoveTrackedFiles(file.Name); err != nil {
+
+				if err := gui.GitCommand.RemoveTrackedFiles(node.GetPath()); err != nil {
+					return err
+				}
+
+				if err := gui.GitCommand.Ignore(node.GetPath()); err != nil {
 					return err
 				}
 				return gui.refreshSidePanels(refreshOptions{scope: []int{FILES}})
@@ -319,7 +338,11 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
 		})
 	}
 
-	if err := gui.GitCommand.Ignore(file.Name); err != nil {
+	if err := unstageFiles(); err != nil {
+		return err
+	}
+
+	if err := gui.GitCommand.Ignore(node.GetPath()); err != nil {
 		return gui.surfaceError(err)
 	}
 
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index ea6e13e99..fc6107a96 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -430,7 +430,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
 			ViewName:    "files",
 			Contexts:    []string{FILES_CONTEXT_KEY},
 			Key:         gui.getKey(config.Files.IgnoreFile),
-			Handler:     gui.handleIgnoreFile,
+			Handler:     gui.wrappedHandler(gui.handleIgnoreFile),
 			Description: gui.Tr.LcIgnoreFile,
 		},
 		{