Repository: jesseduffield/lazygit (language: go)

Issue:
Interactive staging errors out
**Describe the bug**
The interactive staging, where you can stage by chunks/lines does not appear to work.

**To Reproduce**
Steps to reproduce the behavior:

1. Create an empty repository `git init`.
2. Create a file containing two lines.
```
line one
line two
```
3. Commit the file.
4. Edit the file.
```
line one and something
line two
line three
```
5. Select the file and press enter to go the staging view.
6. Select the first chunk `line one and something`.
7. Stage the chunk

**Screenshots**

![Image](https://github.com/user-attachments/assets/57222fd7-7d4d-4e30-93ff-9f9498be70ce)

https://github.com/user-attachments/assets/ba27853a-90e9-4344-876c-b3b7116d3ae8

**Version info:**
```bash
~/g/lazygit-interactive-staging-repro (master)> lazygit --version
commit=, build date=, build source=homebrew, version=0.45.2, os=darwin, arch=arm64, git version=2.48.1
```
```bash
~/g/lazygit-interactive-staging-repro (master)> git --version
git version 2.48.1
```

**Additional context**
OS: MacOS
Terminal Emulator: Ghostty
Shell: fish

I have used `git add -p` to stage the first chunk.
```bash
~/g/lazygit-interactive-staging-repro (master)> git diff
diff --git a/test.txt b/test.txt
index e5c5c55..9b53c18 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,3 @@
-line one
+line one and something
 line two
+line three

~/g/lazygit-interactive-staging-repro (master)> git add -p test.txt
diff --git a/test.txt b/test.txt
index e5c5c55..9b53c18 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,3 @@
-line one
+line one and something
 line two
+line three
(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]? e

~/g/lazygit-interactive-staging-repro (master)> git diff --cached
diff --git a/test.txt b/test.txt
index e5c5c55..92186d0 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,2 @@
-line one
+line one and something
 line two
```

I then used `git diff --cached > p.patch` to make patch that should be similar to what I imagine lazygit is using.
```bash
~/g/lazygit-interactive-staging-repro (master)> git diff --cached > p.patch
~/g/lazygit-interactive-staging-repro (master)> cat p.patch
diff --git a/test.txt b/test.txt
index e5c5c55..92186d0 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,2 @@
-line one
+line one and something
 line two
```

I then reset the staging area with `git restore --staged test.txt`.
```bash
~/g/lazygit-interactive-staging-repro (master)> git restore --staged test.txt
~/g/lazygit-interactive-staging-repro (master)> git diff
diff --git a/test.txt b/test.txt
index e5c5c55..9b53c18 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,3 @@
-line one
+line one and something
 line two
+line three
```

Finally I used `git apply --cached p.patch` and the patch was applied succesfully.
```bash
~/g/lazygit-interactive-staging-repro (master)> git apply --cached p.patch
~/g/lazygit-interactive-staging-repro (master)> git diff
diff --git a/test.txt b/test.txt
index 92186d0..9b53c18 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,3 @@
 line one and something
 line two
+line three
```


Discussion / hints:
This seems to happen only with a diff context size of 0. (Press `{` until it's zero.) Are you using that intentionally?

If I follow your command line scenario and create the patch using `git diff --cached -U0 > p.patch`, trying to apply it fails with the same error message that lazygit gives.

I'm not going to investigate more at this point, but maybe this gives you clues what else to experiment with.

We [only recently](https://github.com/jesseduffield/lazygit/pull/4050) allowed to set the context size all the way down to 0; maybe that wasn't a good idea... (?)
Interesting discussion in the magit repo: https://github.com/magit/magit/issues/4222

What they ended up doing is disabling staging/unstaging when the context size is 0, and I suppose we should simply do the same. The result is pretty much the same as what we have now, except that the error message would be less confusing.

PRs welcome. :)

Fix patch:
diff --git a/pkg/gui/controllers/staging_controller.go b/pkg/gui/controllers/staging_controller.go
index c3ea3ca247f..f353cc2154f 100644
--- a/pkg/gui/controllers/staging_controller.go
+++ b/pkg/gui/controllers/staging_controller.go
@@ -1,11 +1,13 @@
 package controllers
 
 import (
+	"fmt"
 	"strings"
 
 	"github.com/jesseduffield/gocui"
 	"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
 	"github.com/jesseduffield/lazygit/pkg/commands/patch"
+	"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
 	"github.com/jesseduffield/lazygit/pkg/gui/types"
 )
 
@@ -185,10 +187,20 @@ func (self *StagingController) TogglePanel() error {
 }
 
 func (self *StagingController) ToggleStaged() error {
+	if self.c.AppState.DiffContextSize == 0 {
+		return fmt.Errorf(self.c.Tr.Actions.NotEnoughContextToStage,
+			keybindings.Label(self.c.UserConfig().Keybinding.Universal.IncreaseContextInDiffView))
+	}
+
 	return self.applySelectionAndRefresh(self.staged)
 }
 
 func (self *StagingController) DiscardSelection() error {
+	if self.c.AppState.DiffContextSize == 0 {
+		return fmt.Errorf(self.c.Tr.Actions.NotEnoughContextToDiscard,
+			keybindings.Label(self.c.UserConfig().Keybinding.Universal.IncreaseContextInDiffView))
+	}
+
 	reset := func() error { return self.applySelectionAndRefresh(true) }
 
 	if !self.staged && !self.c.UserConfig().Gui.SkipDiscardChangeWarning {
diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go
index 28e12635626..f92c4099354 100644
--- a/pkg/i18n/english.go
+++ b/pkg/i18n/english.go
@@ -926,6 +926,8 @@ type Actions struct {
 	UnstageFile                       string
 	UnstageAllFiles                   string
 	StageAllFiles                     string
+	NotEnoughContextToStage           string
+	NotEnoughContextToDiscard         string
 	IgnoreExcludeFile                 string
 	IgnoreFileErr                     string
 	ExcludeFile                       string
@@ -1913,6 +1915,8 @@ func EnglishTranslationSet() *TranslationSet {
 			UnstageFile:                     "Unstage file",
 			UnstageAllFiles:                 "Unstage all files",
 			StageAllFiles:                   "Stage all files",
+			NotEnoughContextToStage:         "Staging or unstaging changes is not possible with a diff context size of 0. Increase the context using '%s'.",
+			NotEnoughContextToDiscard:       "Discarding changes is not possible with a diff context size of 0. Increase the context using '%s'.",
 			IgnoreExcludeFile:               "Ignore or exclude file",
 			IgnoreFileErr:                   "Cannot ignore .gitignore",
 			ExcludeFile:                     "Exclude file",


Test patch: