diff --git a/pkg/app/app.go b/pkg/app/app.go
index 602dffad2..7a53b2be5 100644
--- a/pkg/app/app.go
+++ b/pkg/app/app.go
@@ -239,7 +239,7 @@ func (app *App) Run() error {
 		os.Exit(0)
 	}
 
-	err := app.Gui.RunWithSubprocesses()
+	err := app.Gui.RunWithRestarts()
 	return err
 }
 
diff --git a/pkg/gui/commit_message_panel.go b/pkg/gui/commit_message_panel.go
index 983d02af8..35d3b0c80 100644
--- a/pkg/gui/commit_message_panel.go
+++ b/pkg/gui/commit_message_panel.go
@@ -11,17 +11,13 @@ import (
 
 // runSyncOrAsyncCommand takes the output of a command that may have returned
 // either no error, an error, or a subprocess to execute, and if a subprocess
-// needs to be set on the gui object, it does so, and then returns the error
-// the bool returned tells us whether the calling code should continue
+// needs to be run, it runs it
 func (gui *Gui) runSyncOrAsyncCommand(sub *exec.Cmd, err error) (bool, error) {
 	if err != nil {
-		if err != gui.Errors.ErrSubProcess {
-			return false, gui.surfaceError(err)
-		}
+		return false, gui.surfaceError(err)
 	}
 	if sub != nil {
-		gui.SubProcess = sub
-		return false, gui.Errors.ErrSubProcess
+		return false, gui.runSubprocessWithSuspense(sub)
 	}
 	return true, nil
 }
diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go
index af4b9feed..811c8613d 100644
--- a/pkg/gui/commits_panel.go
+++ b/pkg/gui/commits_panel.go
@@ -263,8 +263,7 @@ func (gui *Gui) handleRenameCommitEditor() error {
 		return gui.surfaceError(err)
 	}
 	if subProcess != nil {
-		gui.SubProcess = subProcess
-		return gui.Errors.ErrSubProcess
+		return gui.runSubprocessWithSuspense(subProcess)
 	}
 
 	return nil
diff --git a/pkg/gui/custom_commands.go b/pkg/gui/custom_commands.go
index 1411ec34f..09af7065c 100644
--- a/pkg/gui/custom_commands.go
+++ b/pkg/gui/custom_commands.go
@@ -60,8 +60,7 @@ func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand
 			}
 
 			if customCommand.Subprocess {
-				gui.PrepareShellSubProcess(cmdStr)
-				return nil
+				return gui.runSubprocessWithSuspense(gui.OSCommand.PrepareShellSubProcess(cmdStr))
 			}
 
 			loadingText := customCommand.LoadingText
diff --git a/pkg/gui/errors.go b/pkg/gui/errors.go
index d8aa7530d..e0f37d3ea 100644
--- a/pkg/gui/errors.go
+++ b/pkg/gui/errors.go
@@ -5,7 +5,6 @@ import "github.com/go-errors/errors"
 // SentinelErrors are the errors that have special meaning and need to be checked
 // by calling functions. The less of these, the better
 type SentinelErrors struct {
-	ErrSubProcess error
 	ErrNoFiles    error
 	ErrSwitchRepo error
 	ErrRestart    error
@@ -25,7 +24,6 @@ const UNKNOWN_VIEW_ERROR_MSG = "unknown view"
 // localising things in the code.
 func (gui *Gui) GenerateSentinelErrors() {
 	gui.Errors = SentinelErrors{
-		ErrSubProcess: errors.New(gui.Tr.RunningSubprocess),
 		ErrNoFiles:    errors.New(gui.Tr.NoChangedFiles),
 		ErrSwitchRepo: errors.New("switching repo"),
 		ErrRestart:    errors.New("restarting"),
@@ -34,7 +32,6 @@ func (gui *Gui) GenerateSentinelErrors() {
 
 func (gui *Gui) sentinelErrorsArr() []error {
 	return []error{
-		gui.Errors.ErrSubProcess,
 		gui.Errors.ErrNoFiles,
 		gui.Errors.ErrSwitchRepo,
 		gui.Errors.ErrRestart,
diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go
index 2c9640f41..59ec172b3 100644
--- a/pkg/gui/files_panel.go
+++ b/pkg/gui/files_panel.go
@@ -17,7 +17,6 @@ import (
 	"github.com/jesseduffield/lazygit/pkg/config"
 	"github.com/jesseduffield/lazygit/pkg/gui/filetree"
 	"github.com/jesseduffield/lazygit/pkg/utils"
-	"github.com/mgutz/str"
 )
 
 // list panel functions
@@ -475,24 +474,9 @@ func (gui *Gui) handleCommitEditorPress() error {
 		return gui.promptToStageAllAndRetry(gui.handleCommitEditorPress)
 	}
 
-	gui.PrepareSubProcess("git commit")
-	return nil
-}
-
-// PrepareSubProcess - prepare a subprocess for execution and tell the gui to switch to it
-func (gui *Gui) PrepareSubProcess(command string) {
-	splitCmd := str.ToArgv(command)
-	gui.SubProcess = gui.OSCommand.PrepareSubProcess(splitCmd[0], splitCmd[1:]...)
-	gui.g.Update(func(g *gocui.Gui) error {
-		return gui.Errors.ErrSubProcess
-	})
-}
-
-func (gui *Gui) PrepareShellSubProcess(command string) {
-	gui.SubProcess = gui.OSCommand.PrepareShellSubProcess(command)
-	gui.g.Update(func(g *gocui.Gui) error {
-		return gui.Errors.ErrSubProcess
-	})
+	return gui.runSubprocessWithSuspense(
+		gui.OSCommand.PrepareSubProcess("git", "commit"),
+	)
 }
 
 func (gui *Gui) editFile(filename string) error {
@@ -816,8 +800,9 @@ func (gui *Gui) handleCustomCommand() error {
 	return gui.prompt(promptOpts{
 		title: gui.Tr.CustomCommand,
 		handleConfirm: func(command string) error {
-			gui.SubProcess = gui.OSCommand.PrepareShellSubProcess(command)
-			return gui.Errors.ErrSubProcess
+			return gui.runSubprocessWithSuspense(
+				gui.OSCommand.PrepareShellSubProcess(command),
+			)
 		},
 	})
 }
diff --git a/pkg/gui/git_flow.go b/pkg/gui/git_flow.go
index 4440c6ebd..6af93794c 100644
--- a/pkg/gui/git_flow.go
+++ b/pkg/gui/git_flow.go
@@ -31,9 +31,9 @@ func (gui *Gui) gitFlowFinishBranch(gitFlowConfig string, branchName string) err
 		return gui.createErrorPanel(gui.Tr.NotAGitFlowBranch)
 	}
 
-	subProcess := gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "finish", suffix)
-	gui.SubProcess = subProcess
-	return gui.Errors.ErrSubProcess
+	return gui.runSubprocessWithSuspense(
+		gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "finish", suffix),
+	)
 }
 
 func (gui *Gui) handleCreateGitFlowMenu() error {
@@ -55,9 +55,9 @@ func (gui *Gui) handleCreateGitFlowMenu() error {
 			return gui.prompt(promptOpts{
 				title: title,
 				handleConfirm: func(name string) error {
-					subProcess := gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "start", name)
-					gui.SubProcess = subProcess
-					return gui.Errors.ErrSubProcess
+					return gui.runSubprocessWithSuspense(
+						gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "start", name),
+					)
 				},
 			})
 		}
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index b44994c32..2e58f430d 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -476,10 +476,9 @@ func (gui *Gui) Run() error {
 	return err
 }
 
-// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
-// if the error returned from a run is a ErrSubProcess, it runs the subprocess
-// otherwise it handles the error, possibly by quitting the application
-func (gui *Gui) RunWithSubprocesses() error {
+// RunWithRestarts loops, instantiating a new gocui.Gui with each iteration
+// (i.e. when switching repos or restarting). If it's a random error, we quit
+func (gui *Gui) RunWithRestarts() error {
 	gui.StartTime = time.Now()
 	go utils.Safe(gui.replayRecordedEvents)
 
@@ -512,11 +511,6 @@ func (gui *Gui) RunWithSubprocesses() error {
 				return nil
 			case gui.Errors.ErrSwitchRepo, gui.Errors.ErrRestart:
 				continue
-			case gui.Errors.ErrSubProcess:
-
-				if err := gui.runCommand(); err != nil {
-					return err
-				}
 			default:
 				return err
 			}
@@ -524,23 +518,40 @@ func (gui *Gui) RunWithSubprocesses() error {
 	}
 }
 
-func (gui *Gui) runCommand() error {
-	gui.SubProcess.Stdout = os.Stdout
-	gui.SubProcess.Stderr = os.Stdout
-	gui.SubProcess.Stdin = os.Stdin
+func (gui *Gui) runSubprocessWithSuspense(subprocess *exec.Cmd) error {
+	if err := gocui.Screen.Suspend(); err != nil {
+		return gui.surfaceError(err)
+	}
 
-	fmt.Fprintf(os.Stdout, "\n%s\n\n", utils.ColoredString("+ "+strings.Join(gui.SubProcess.Args, " "), color.FgBlue))
+	cmdErr := gui.runSubprocess(subprocess)
 
-	if err := gui.SubProcess.Run(); err != nil {
+	if err := gocui.Screen.Resume(); err != nil {
+		return gui.surfaceError(err)
+	}
+
+	if err := gui.refreshSidePanels(refreshOptions{mode: ASYNC}); err != nil {
+		return err
+	}
+
+	return gui.surfaceError(cmdErr)
+}
+
+func (gui *Gui) runSubprocess(subprocess *exec.Cmd) error {
+	subprocess.Stdout = os.Stdout
+	subprocess.Stderr = os.Stdout
+	subprocess.Stdin = os.Stdin
+
+	fmt.Fprintf(os.Stdout, "\n%s\n\n", utils.ColoredString("+ "+strings.Join(subprocess.Args, " "), color.FgBlue))
+
+	if err := subprocess.Run(); err != nil {
 		// not handling the error explicitly because usually we're going to see it
 		// in the output anyway
 		gui.Log.Error(err)
 	}
 
-	gui.SubProcess.Stdout = ioutil.Discard
-	gui.SubProcess.Stderr = ioutil.Discard
-	gui.SubProcess.Stdin = nil
-	gui.SubProcess = nil
+	subprocess.Stdout = ioutil.Discard
+	subprocess.Stderr = ioutil.Discard
+	subprocess.Stdin = nil
 
 	fmt.Fprintf(os.Stdout, "\n%s", utils.ColoredString(gui.Tr.PressEnterToReturn, color.FgGreen))
 	fmt.Scanln() // wait for enter press
diff --git a/pkg/gui/rebase_options_panel.go b/pkg/gui/rebase_options_panel.go
index 5ffd7b3bd..01f91d3cb 100644
--- a/pkg/gui/rebase_options_panel.go
+++ b/pkg/gui/rebase_options_panel.go
@@ -50,8 +50,7 @@ func (gui *Gui) genericMergeCommand(command string) error {
 	if status == commands.REBASE_MODE_MERGING && command != "abort" && gui.Config.GetUserConfig().Git.Merging.ManualCommit {
 		sub := gui.OSCommand.PrepareSubProcess("git", commandType, fmt.Sprintf("--%s", command))
 		if sub != nil {
-			gui.SubProcess = sub
-			return gui.Errors.ErrSubProcess
+			return gui.runSubprocessWithSuspense(sub)
 		}
 		return nil
 	}
@@ -68,8 +67,6 @@ func (gui *Gui) handleGenericMergeCommandResult(result error) error {
 	}
 	if result == nil {
 		return nil
-	} else if result == gui.Errors.ErrSubProcess {
-		return result
 	} else if strings.Contains(result.Error(), "No changes - did you forget to use") {
 		return gui.genericMergeCommand("skip")
 	} else if strings.Contains(result.Error(), "The previous cherry-pick is now empty") {