repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

commit
674b407
parent
8967f63
author
Eric Bower
date
2025-12-13 11:21:20 -0500 EST
chore(range-diff): more tests
12 files changed,  +634, -5
M .gitignore
+1, -0
1@@ -17,3 +17,4 @@ test.db
2 review.patch
3 .aider*
4 git_src/
5+.beads/
A fixtures/a_c_changed_message.patch
+56, -0
 1@@ -0,0 +1,56 @@
 2+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
 3+From: Eric Bower <me@erock.io>
 4+Date: Tue, 23 Jul 2024 10:07:57 -0400
 5+Subject: [PATCH 1/2] chore: add torch and create random tensor
 6+
 7+---
 8+ requirements.txt | 1 +
 9+ train.py         | 3 +++
10+ 2 files changed, 4 insertions(+)
11+ create mode 100644 requirements.txt
12+
13+diff --git a/requirements.txt b/requirements.txt
14+new file mode 100644
15+index 0000000..4968a39
16+--- /dev/null
17++++ b/requirements.txt
18+@@ -0,0 +1 @@
19++torch==2.3.1
20+diff --git a/train.py b/train.py
21+index 5c027f4..d21dac3 100644
22+--- a/train.py
23++++ b/train.py
24+@@ -1,2 +1,5 @@
25++import torch
26++
27+ if __name__ == "__main__":
28+     print("train!")
29++    torch.rand(3,6)
30+-- 
31+2.45.2
32+
33+
34+From ddeeff1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
35+From: Eric Bower <me@erock.io>
36+Date: Tue, 23 Jul 2024 10:14:37 -0400
37+Subject: [PATCH 2/2] docs: readme
38+
39+Also a silly comment here!
40+
41+---
42+ README.md | 4 +++-
43+ 1 file changed, 3 insertions(+), 1 deletion(-)
44+
45+diff --git a/README.md b/README.md
46+index 8f3a780..3043953 100644
47+--- a/README.md
48++++ b/README.md
49+@@ -1,3 +1,5 @@
50+ # Let's build an RNN
51+
52+-This repo demonstrates building an RNN using `pytorch`
53++This repo demonstrates building an RNN using `pytorch`.
54++
55++Here is some more readme information.
56+-- 
57+2.45.2
A fixtures/a_c_different_author.patch
+54, -0
 1@@ -0,0 +1,54 @@
 2+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
 3+From: Alice Smith <alice@example.com>
 4+Date: Tue, 23 Jul 2024 10:07:57 -0400
 5+Subject: [PATCH 1/2] chore: add torch and create random tensor
 6+
 7+---
 8+ requirements.txt | 1 +
 9+ train.py         | 3 +++
10+ 2 files changed, 4 insertions(+)
11+ create mode 100644 requirements.txt
12+
13+diff --git a/requirements.txt b/requirements.txt
14+new file mode 100644
15+index 0000000..4968a39
16+--- /dev/null
17++++ b/requirements.txt
18+@@ -0,0 +1 @@
19++torch==2.3.1
20+diff --git a/train.py b/train.py
21+index 5c027f4..d21dac3 100644
22+--- a/train.py
23++++ b/train.py
24+@@ -1,2 +1,5 @@
25++import torch
26++
27+ if __name__ == "__main__":
28+     print("train!")
29++    torch.rand(3,6)
30+-- 
31+2.45.2
32+
33+
34+From 22dde1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
35+From: Alice Smith <alice@example.com>
36+Date: Tue, 23 Jul 2024 10:14:37 -0400
37+Subject: [PATCH 2/2] docs: readme
38+
39+---
40+ README.md | 4 +++-
41+ 1 file changed, 3 insertions(+), 1 deletion(-)
42+
43+diff --git a/README.md b/README.md
44+index 8f3a780..3043953 100644
45+--- a/README.md
46++++ b/README.md
47+@@ -1,3 +1,5 @@
48+ # Let's build an RNN
49+
50+-This repo demonstrates building an RNN using `pytorch`
51++This repo demonstrates building an RNN using `pytorch`.
52++
53++Here is some more readme information.
54+-- 
55+2.45.2
A fixtures/a_c_file_added_removed.patch
+72, -0
 1@@ -0,0 +1,72 @@
 2+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
 3+From: Eric Bower <me@erock.io>
 4+Date: Tue, 23 Jul 2024 10:07:57 -0400
 5+Subject: [PATCH 1/3] chore: add torch and create random tensor
 6+
 7+---
 8+ requirements.txt | 1 +
 9+ train.py         | 3 +++
10+ 2 files changed, 4 insertions(+)
11+ create mode 100644 requirements.txt
12+
13+diff --git a/requirements.txt b/requirements.txt
14+new file mode 100644
15+index 0000000..4968a39
16+--- /dev/null
17++++ b/requirements.txt
18+@@ -0,0 +1 @@
19++torch==2.3.1
20+diff --git a/train.py b/train.py
21+index 5c027f4..d21dac3 100644
22+--- a/train.py
23++++ b/train.py
24+@@ -1,2 +1,5 @@
25++import torch
26++
27+ if __name__ == "__main__":
28+     print("train!")
29++    torch.rand(3,6)
30+-- 
31+2.45.2
32+
33+
34+From aabbdd1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
35+From: Eric Bower <me@erock.io>
36+Date: Tue, 23 Jul 2024 10:14:37 -0400
37+Subject: [PATCH 2/3] chore: add temp file
38+
39+---
40+ temp.txt | 1 +
41+ 1 file changed, 1 insertion(+)
42+ create mode 100644 temp.txt
43+
44+diff --git a/temp.txt b/temp.txt
45+new file mode 100644
46+index 0000000..9876543
47+--- /dev/null
48++++ b/temp.txt
49+@@ -0,0 +1 @@
50++temporary content
51+-- 
52+2.45.2
53+
54+
55+From ccddee1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
56+From: Eric Bower <me@erock.io>
57+Date: Tue, 23 Jul 2024 10:20:00 -0400
58+Subject: [PATCH 3/3] chore: remove temp file
59+
60+---
61+ temp.txt | 1 -
62+ 1 file changed, 1 deletion(-)
63+ delete mode 100644 temp.txt
64+
65+diff --git a/temp.txt b/temp.txt
66+deleted file mode 100644
67+index 9876543..0000000
68+--- a/temp.txt
69++++ /dev/null
70+@@ -1 +0,0 @@
71+-temporary content
72+-- 
73+2.45.2
A fixtures/a_c_mode_change.patch
+57, -0
 1@@ -0,0 +1,57 @@
 2+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
 3+From: Eric Bower <me@erock.io>
 4+Date: Tue, 23 Jul 2024 10:07:57 -0400
 5+Subject: [PATCH 1/2] chore: add torch and create random tensor + add script
 6+
 7+---
 8+ requirements.txt | 1 +
 9+ train.py         | 3 +++
10+ run.sh           | 2 ++
11+ 3 files changed, 6 insertions(+)
12+ create mode 100644 requirements.txt
13+ create mode 100644 run.sh
14+
15+diff --git a/requirements.txt b/requirements.txt
16+new file mode 100644
17+index 0000000..4968a39
18+--- /dev/null
19++++ b/requirements.txt
20+@@ -0,0 +1 @@
21++torch==2.3.1
22+diff --git a/train.py b/train.py
23+index 5c027f4..d21dac3 100644
24+--- a/train.py
25++++ b/train.py
26+@@ -1,2 +1,5 @@
27++import torch
28++
29+ if __name__ == "__main__":
30+     print("train!")
31++    torch.rand(3,6)
32+diff --git a/run.sh b/run.sh
33+new file mode 100644
34+index 0000000..1234567
35+--- /dev/null
36++++ b/run.sh
37+@@ -0,0 +1,2 @@
38++#!/bin/bash
39++python train.py
40+-- 
41+2.45.2
42+
43+
44+From aabb001259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
45+From: Eric Bower <me@erock.io>
46+Date: Tue, 23 Jul 2024 10:14:37 -0400
47+Subject: [PATCH 2/2] chore: make script executable
48+
49+---
50+ run.sh | 0
51+ 1 file changed, 0 insertions(+), 0 deletions(-)
52+ mode change 100644 => 100755 run.sh
53+
54+diff --git a/run.sh b/run.sh
55+old mode 100644
56+new mode 100755
57+-- 
58+2.45.2
A fixtures/a_c_multi_file_change.patch
+78, -0
 1@@ -0,0 +1,78 @@
 2+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
 3+From: Eric Bower <me@erock.io>
 4+Date: Tue, 23 Jul 2024 10:07:57 -0400
 5+Subject: [PATCH 1/2] chore: add torch and create random tensor
 6+
 7+---
 8+ requirements.txt | 1 +
 9+ train.py         | 3 +++
10+ 2 files changed, 4 insertions(+)
11+ create mode 100644 requirements.txt
12+
13+diff --git a/requirements.txt b/requirements.txt
14+new file mode 100644
15+index 0000000..4968a39
16+--- /dev/null
17++++ b/requirements.txt
18+@@ -0,0 +1 @@
19++torch==2.3.1
20+diff --git a/train.py b/train.py
21+index 5c027f4..d21dac3 100644
22+--- a/train.py
23++++ b/train.py
24+@@ -1,2 +1,5 @@
25++import torch
26++
27+ if __name__ == "__main__":
28+     print("train!")
29++    torch.rand(3,6)
30+-- 
31+2.45.2
32+
33+
34+From bbccdd1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
35+From: Eric Bower <me@erock.io>
36+Date: Tue, 23 Jul 2024 10:14:37 -0400
37+Subject: [PATCH 2/2] docs: update readme and add contributing guide
38+
39+---
40+ README.md      | 4 +++-
41+ CONTRIBUTING.md | 5 +++++
42+ LICENSE.md     | 3 +++
43+ 3 files changed, 11 insertions(+), 1 deletion(-)
44+ create mode 100644 CONTRIBUTING.md
45+ create mode 100644 LICENSE.md
46+
47+diff --git a/README.md b/README.md
48+index 8f3a780..3043953 100644
49+--- a/README.md
50++++ b/README.md
51+@@ -1,3 +1,5 @@
52+ # Let's build an RNN
53+
54+-This repo demonstrates building an RNN using `pytorch`
55++This repo demonstrates building an RNN using `pytorch`.
56++
57++Here is some more readme information.
58+diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
59+new file mode 100644
60+index 0000000..1234567
61+--- /dev/null
62++++ b/CONTRIBUTING.md
63+@@ -0,0 +1,5 @@
64++# Contributing
65++
66++1. Fork the repo
67++2. Make changes
68++3. Submit a PR
69+diff --git a/LICENSE.md b/LICENSE.md
70+new file mode 100644
71+index 0000000..7654321
72+--- /dev/null
73++++ b/LICENSE.md
74+@@ -0,0 +1,3 @@
75++# MIT License
76++
77++Copyright 2024
78+-- 
79+2.45.2
A fixtures/a_c_renamed_file.patch
+58, -0
 1@@ -0,0 +1,58 @@
 2+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
 3+From: Eric Bower <me@erock.io>
 4+Date: Tue, 23 Jul 2024 10:07:57 -0400
 5+Subject: [PATCH 1/2] chore: add torch and create random tensor
 6+
 7+---
 8+ requirements.txt | 1 +
 9+ train.py         | 3 +++
10+ 2 files changed, 4 insertions(+)
11+ create mode 100644 requirements.txt
12+
13+diff --git a/requirements.txt b/requirements.txt
14+new file mode 100644
15+index 0000000..4968a39
16+--- /dev/null
17++++ b/requirements.txt
18+@@ -0,0 +1 @@
19++torch==2.3.1
20+diff --git a/train.py b/train.py
21+index 5c027f4..d21dac3 100644
22+--- a/train.py
23++++ b/train.py
24+@@ -1,2 +1,5 @@
25++import torch
26++
27+ if __name__ == "__main__":
28+     print("train!")
29++    torch.rand(3,6)
30+-- 
31+2.45.2
32+
33+
34+From aabbcc1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
35+From: Eric Bower <me@erock.io>
36+Date: Tue, 23 Jul 2024 10:14:37 -0400
37+Subject: [PATCH 2/2] docs: readme + rename file
38+
39+---
40+ README.md => DOCS.md | 4 +++-
41+ 1 file changed, 3 insertions(+), 1 deletion(-)
42+ rename README.md => DOCS.md (60%)
43+
44+diff --git a/README.md b/DOCS.md
45+similarity index 60%
46+rename from README.md
47+rename to DOCS.md
48+index 8f3a780..3043953 100644
49+--- a/README.md
50++++ b/DOCS.md
51+@@ -1,3 +1,5 @@
52+ # Let's build an RNN
53+
54+-This repo demonstrates building an RNN using `pytorch`
55++This repo demonstrates building an RNN using `pytorch`.
56++
57++Here is some more readme information.
58+-- 
59+2.45.2
A fixtures/a_c_split.patch
+66, -0
 1@@ -0,0 +1,66 @@
 2+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
 3+From: Eric Bower <me@erock.io>
 4+Date: Tue, 23 Jul 2024 10:07:57 -0400
 5+Subject: [PATCH 1/3] chore: add torch dependency
 6+
 7+---
 8+ requirements.txt | 1 +
 9+ 1 file changed, 1 insertion(+)
10+ create mode 100644 requirements.txt
11+
12+diff --git a/requirements.txt b/requirements.txt
13+new file mode 100644
14+index 0000000..4968a39
15+--- /dev/null
16++++ b/requirements.txt
17+@@ -0,0 +1 @@
18++torch==2.3.1
19+-- 
20+2.45.2
21+
22+
23+From aabb1122c27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
24+From: Eric Bower <me@erock.io>
25+Date: Tue, 23 Jul 2024 10:10:00 -0400
26+Subject: [PATCH 2/3] chore: use torch in train.py
27+
28+---
29+ train.py | 3 +++
30+ 1 file changed, 3 insertions(+)
31+
32+diff --git a/train.py b/train.py
33+index 5c027f4..d21dac3 100644
34+--- a/train.py
35++++ b/train.py
36+@@ -1,2 +1,5 @@
37++import torch
38++
39+ if __name__ == "__main__":
40+     print("train!")
41++    torch.rand(3,6)
42+-- 
43+2.45.2
44+
45+
46+From 22dde1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
47+From: Eric Bower <me@erock.io>
48+Date: Tue, 23 Jul 2024 10:14:37 -0400
49+Subject: [PATCH 3/3] docs: readme
50+
51+---
52+ README.md | 4 +++-
53+ 1 file changed, 3 insertions(+), 1 deletion(-)
54+
55+diff --git a/README.md b/README.md
56+index 8f3a780..3043953 100644
57+--- a/README.md
58++++ b/README.md
59+@@ -1,3 +1,5 @@
60+ # Let's build an RNN
61+
62+-This repo demonstrates building an RNN using `pytorch`
63++This repo demonstrates building an RNN using `pytorch`.
64++
65++Here is some more readme information.
66+-- 
67+2.45.2
A fixtures/a_c_squashed.patch
+44, -0
 1@@ -0,0 +1,44 @@
 2+From aabbccdd1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
 3+From: Eric Bower <me@erock.io>
 4+Date: Tue, 23 Jul 2024 10:07:57 -0400
 5+Subject: [PATCH] chore: add torch and update readme
 6+
 7+This commit combines the torch addition and readme update.
 8+
 9+---
10+ README.md        | 4 +++-
11+ requirements.txt | 1 +
12+ train.py         | 3 +++
13+ 3 files changed, 7 insertions(+), 1 deletion(-)
14+ create mode 100644 requirements.txt
15+
16+diff --git a/README.md b/README.md
17+index 8f3a780..3043953 100644
18+--- a/README.md
19++++ b/README.md
20+@@ -1,3 +1,5 @@
21+ # Let's build an RNN
22+
23+-This repo demonstrates building an RNN using `pytorch`
24++This repo demonstrates building an RNN using `pytorch`.
25++
26++Here is some more readme information.
27+diff --git a/requirements.txt b/requirements.txt
28+new file mode 100644
29+index 0000000..4968a39
30+--- /dev/null
31++++ b/requirements.txt
32+@@ -0,0 +1 @@
33++torch==2.3.1
34+diff --git a/train.py b/train.py
35+index 5c027f4..d21dac3 100644
36+--- a/train.py
37++++ b/train.py
38+@@ -1,2 +1,5 @@
39++import torch
40++
41+ if __name__ == "__main__":
42+     print("train!")
43++    torch.rand(3,6)
44+-- 
45+2.45.2
A fixtures/empty.patch
+1, -0
1@@ -0,0 +1 @@
2+
M range_diff.go
+7, -1
 1@@ -331,7 +331,13 @@ func RangeDiffToStr(diffs []*RangeDiffOutput) string {
 2 	for _, diff := range diffs {
 3 		output += diff.Header.String()
 4 		for _, f := range diff.Files {
 5-			output += fmt.Sprintf("\n@@ %s\n", f.NewFile.NewName)
 6+			fileName := ""
 7+			if f.NewFile != nil {
 8+				fileName = f.NewFile.NewName
 9+			} else if f.OldFile != nil {
10+				fileName = f.OldFile.NewName
11+			}
12+			output += fmt.Sprintf("\n@@ %s\n", fileName)
13 			for _, d := range f.Diff {
14 				switch d.OuterType {
15 				case "equal":
M range_diff_test.go
+140, -4
  1@@ -180,7 +180,18 @@ func TestRangeDiffChangedCommit(t *testing.T) {
  2 	    Z 10
  3 	    Z B
  4 */
  5-// func TestRangeDiffRenamedFile(t *testing.T) {}
  6+func TestRangeDiffRenamedFile(t *testing.T) {
  7+	actual := cmp("a_b_reorder.patch", "a_c_renamed_file.patch")
  8+	if !strings.Contains(actual, "1:  33c682a = 1:  33c682a") {
  9+		t.Fatal("expected first commit to be equal")
 10+	}
 11+	if !strings.Contains(actual, "2:  22dde12 ! 2:  aabbcc1") {
 12+		t.Fatal("expected second commit to show diff marker")
 13+	}
 14+	if !strings.Contains(actual, "DOCS.md") {
 15+		t.Fatal("expected renamed file DOCS.md in output")
 16+	}
 17+}
 18 
 19 // file with mode only change
 20 /*
 21@@ -218,7 +229,15 @@ func TestRangeDiffChangedCommit(t *testing.T) {
 22 	    + ## other-file (mode change 100644 => 100755) ##
 23 	3:  $(test_oid t4) = 3:  $(test_oid o3) s/12/B/
 24 */
 25-// func TestRangeDiffFileWithModeOnlyChange(t *testing.T) {}
 26+func TestRangeDiffFileWithModeOnlyChange(t *testing.T) {
 27+	actual := cmp("a_b_reorder.patch", "a_c_mode_change.patch")
 28+	if !strings.Contains(actual, "1:  33c682a ! 1:  33c682a") {
 29+		t.Fatal("expected first commit to show diff marker due to new file")
 30+	}
 31+	if !strings.Contains(actual, "run.sh") {
 32+		t.Fatal("expected run.sh script in output")
 33+	}
 34+}
 35 
 36 // file added and later removed
 37 /*
 38@@ -257,7 +276,18 @@ func TestRangeDiffChangedCommit(t *testing.T) {
 39 	    + ## new-file (deleted) ##
 40 	4:  $(test_oid t4) = 4:  $(test_oid s4) s/12/B/
 41 */
 42-// func TestRangeDiffFileAddedThenRemoved(t *testing.T) {}
 43+func TestRangeDiffFileAddedThenRemoved(t *testing.T) {
 44+	actual := cmp("a_b_reorder.patch", "a_c_file_added_removed.patch")
 45+	if !strings.Contains(actual, "1:  33c682a = 1:  33c682a") {
 46+		t.Fatal("expected first commit to be equal")
 47+	}
 48+	if !strings.Contains(actual, "temp.txt") {
 49+		t.Fatal("expected temp.txt in output")
 50+	}
 51+	if !strings.Contains(actual, "-:  ------- > 3:  ccddee1") {
 52+		t.Fatal("expected third commit to be added")
 53+	}
 54+}
 55 
 56 // changed message
 57 /*
 58@@ -275,4 +305,110 @@ func TestRangeDiffChangedCommit(t *testing.T) {
 59 	3:  $(test_oid t3) = 3:  $(test_oid m3) s/11/B/
 60 	4:  $(test_oid t4) = 4:  $(test_oid m4) s/12/B/
 61 */
 62-// func TestRangeDiffChangedMessage(t *testing.T) {}
 63+func TestRangeDiffChangedMessage(t *testing.T) {
 64+	actual := cmp("a_b_reorder.patch", "a_c_changed_message.patch")
 65+	if !strings.Contains(actual, "1:  33c682a = 1:  33c682a") {
 66+		t.Fatal("expected first commit to be equal")
 67+	}
 68+	if !strings.Contains(actual, "2:  22dde12 ! 2:  ddeeff1") {
 69+		t.Fatal("expected second commit to show diff marker due to message change")
 70+	}
 71+}
 72+
 73+func TestRangeDiffEmptyPatchset(t *testing.T) {
 74+	a, err := fixtures.Fixtures.Open("a_b_reorder.patch")
 75+	bail(err)
 76+	aPatches, err := ParsePatchset(a)
 77+	bail(err)
 78+	bPatches := []*Patch{}
 79+
 80+	actual := RangeDiff(aPatches, bPatches)
 81+	result := RangeDiffToStr(actual)
 82+
 83+	if len(aPatches) != 2 {
 84+		t.Fatalf("expected 2 patches in a, got %d", len(aPatches))
 85+	}
 86+	if !strings.Contains(result, "< -:") {
 87+		t.Fatal("expected removed commit markers when comparing to empty patchset")
 88+	}
 89+	if !strings.Contains(result, "1:  33c682a < -:") {
 90+		t.Fatal("expected first commit to show as removed")
 91+	}
 92+	if !strings.Contains(result, "2:  22dde12 < -:") {
 93+		t.Fatal("expected second commit to show as removed")
 94+	}
 95+}
 96+
 97+func TestRangeDiffEmptyToNonEmpty(t *testing.T) {
 98+	b, err := fixtures.Fixtures.Open("a_b_reorder.patch")
 99+	bail(err)
100+	bPatches, err := ParsePatchset(b)
101+	bail(err)
102+	aPatches := []*Patch{}
103+
104+	actual := RangeDiff(aPatches, bPatches)
105+	result := RangeDiffToStr(actual)
106+
107+	if len(bPatches) != 2 {
108+		t.Fatalf("expected 2 patches in b, got %d", len(bPatches))
109+	}
110+	if !strings.Contains(result, "> 1:") {
111+		t.Fatal("expected added commit markers when comparing from empty patchset")
112+	}
113+	if !strings.Contains(result, "-:  ------- > 1:  33c682a") {
114+		t.Fatal("expected first commit to show as added")
115+	}
116+}
117+
118+func TestRangeDiffSquashedCommits(t *testing.T) {
119+	actual := cmp("a_b_reorder.patch", "a_c_squashed.patch")
120+
121+	if !strings.Contains(actual, "< -:") {
122+		t.Fatal("expected at least one commit to show as removed (squashed away)")
123+	}
124+	if !strings.Contains(actual, "aabbccd") {
125+		t.Fatal("expected squashed commit sha in output")
126+	}
127+}
128+
129+func TestRangeDiffSplitCommits(t *testing.T) {
130+	actual := cmp("a_b_reorder.patch", "a_c_split.patch")
131+
132+	if !strings.Contains(actual, "-:  ------- >") {
133+		t.Fatal("expected added commit marker for split commit")
134+	}
135+	if !strings.Contains(actual, "aabb112") {
136+		t.Fatal("expected new split commit sha (aabb112) in output")
137+	}
138+	if !strings.Contains(actual, "33c682a") {
139+		t.Fatal("expected original commit sha in output")
140+	}
141+}
142+
143+func TestRangeDiffDifferentAuthor(t *testing.T) {
144+	actual := cmp("a_b_reorder.patch", "a_c_different_author.patch")
145+
146+	if !strings.Contains(actual, "!") {
147+		t.Fatal("expected diff marker (!) for commits with different author")
148+	}
149+	if !strings.Contains(actual, "33c682a") && !strings.Contains(actual, "22dde12") {
150+		t.Fatal("expected commit shas in output")
151+	}
152+}
153+
154+func TestRangeDiffMultipleFilesInCommit(t *testing.T) {
155+	actual := cmp("a_b_reorder.patch", "a_c_multi_file_change.patch")
156+
157+	if !strings.Contains(actual, "1:  33c682a = 1:  33c682a") {
158+		t.Fatal("expected first commit to be equal")
159+	}
160+	if !strings.Contains(actual, "2:  22dde12 ! 2:  bbccdd1") {
161+		t.Fatal("expected second commit to show diff marker")
162+	}
163+	if !strings.Contains(actual, "CONTRIBUTING.md") {
164+		t.Fatal("expected CONTRIBUTING.md in diff output")
165+	}
166+	if !strings.Contains(actual, "LICENSE.md") {
167+		t.Fatal("expected LICENSE.md in diff output")
168+	}
169+}