Repository: jesseduffield/lazygit (Go)

Issue:
git config status.renames=copies messes up staging
### Describe the bug

**UPDATE** Opened a PR https://github.com/jesseduffield/lazygit/issues/4892

If you set 

```toml
[status]
  renames=copies
```

The algo of rename detection is different than `true`. Now it detects based on threshold (50%) of content similarity.

This trips up lazygit status view and staging gets broken

### To Reproduce
Steps to reproduce the behavior:

1. `git init`
2. `git config status.renames copies`
3. `echo foo > foo && git add . && git commit -m foo`
4. `cp foo foo2`
5. `mv foo foo1`
6.  now `lazygit` and stage all files

### Expected behavior

`git status` shows this scenario as

<img width="515" height="140" alt="Image" src="https://github.com/user-attachments/assets/cd981375-d3c5-4d7f-9e97-4c5aa014520f" />

So we should either support the `copied` status or explicitly state we don't support `renames=copies|copy` I guess.

### Screenshots

<img width="551" height="205" alt="Image" src="https://github.com/user-attachments/assets/15a116dc-df5b-4a6b-b73e-0e5b60c7e532" />

### Version info:

* _Run `lazygit --version` and paste the result here_
commit=, build date=, build source=Homebrew, version=HEAD-0d5a410, os=darwin, arch=arm64, git version=2.51.0

* _Run `git --version` and paste the result here_
git version 2.51.0


Discussion:

Patch:
diff --git a/pkg/commands/git_commands/file_loader.go b/pkg/commands/git_commands/file_loader.go
index 19c07ece138..36ab8ef6742 100644
--- a/pkg/commands/git_commands/file_loader.go
+++ b/pkg/commands/git_commands/file_loader.go
@@ -201,8 +201,8 @@ func (self *FileLoader) gitStatus(opts GitStatusOptions) ([]FileStatus, error) {
 			PreviousPath: "",
 		}
 
-		if strings.HasPrefix(status.Change, "R") {
-			// if a line starts with 'R' then the next line is the original file.
+		if strings.HasPrefix(status.Change, "R") || strings.HasPrefix(status.Change, "C") {
+			// if a line starts with 'R' (rename) or 'C' (copy) then the next line is the original file.
 			status.PreviousPath = splitLines[i+1]
 			status.StatusString = fmt.Sprintf("%s %s -> %s", status.Change, status.PreviousPath, status.Path)
 			i++


Test patch:
diff --git a/pkg/commands/git_commands/file_loader_test.go b/pkg/commands/git_commands/file_loader_test.go
index 80373eef1b3..ec1f502f1a8 100644
--- a/pkg/commands/git_commands/file_loader_test.go
+++ b/pkg/commands/git_commands/file_loader_test.go
@@ -192,6 +192,43 @@ func TestFileGetStatusFiles(t *testing.T) {
 				},
 			},
 		},
+		{
+			testName:            "Copied files",
+			similarityThreshold: 50,
+			runner: oscommands.NewFakeRunner(t).
+				ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"},
+					"C  copy1.txt\x00original.txt\x00CM copy2.txt\x00original.txt",
+					nil,
+				),
+			expectedFiles: []*models.File{
+				{
+					Path:                    "copy1.txt",
+					PreviousPath:            "original.txt",
+					HasStagedChanges:        true,
+					HasUnstagedChanges:      false,
+					Tracked:                 true,
+					Added:                   false,
+					Deleted:                 false,
+					HasMergeConflicts:       false,
+					HasInlineMergeConflicts: false,
+					DisplayString:           "C  original.txt -> copy1.txt",
+					ShortStatus:             "C ",
+				},
+				{
+					Path:                    "copy2.txt",
+					PreviousPath:            "original.txt",
+					HasStagedChanges:        true,
+					HasUnstagedChanges:      true,
+					Tracked:                 true,
+					Added:                   false,
+					Deleted:                 false,
+					HasMergeConflicts:       false,
+					HasInlineMergeConflicts: false,
+					DisplayString:           "CM original.txt -> copy2.txt",
+					ShortStatus:             "CM",
+				},
+			},
+		},
 	}
 
 	for _, s := range scenarios {