1#!/bin/sh
2#
3# Copyright (c) 2018 Phillip Wood
4#
5
6test_description='git rebase interactive fixup options
7
8This test checks the "fixup [-C|-c]" command of rebase interactive.
9In addition to amending the contents of the commit, "fixup -C"
10replaces the original commit message with the message of the fixup
11commit. "fixup -c" also replaces the original message, but opens the
12editor to allow the user to edit the message before committing. Similar
13to the "fixup" command that works with "fixup!", "fixup -C" works with
14"amend!" upon --autosquash.
15'
16
17. ./test-lib.sh
18
19. "$TEST_DIRECTORY"/lib-rebase.sh
20
21EMPTY=""
22
23# test_commit_message <rev> -m <msg>
24# test_commit_message <rev> <path>
25# Verify that the commit message of <rev> matches
26# <msg> or the content of <path>.
27test_commit_message () {
28	git show --no-patch --pretty=format:%B "$1" >actual &&
29	case "$2" in
30	-m)
31		echo "$3" >expect &&
32		test_cmp expect actual ;;
33	*)
34		test_cmp "$2" actual ;;
35	esac
36}
37
38get_author () {
39	rev="$1" &&
40	git log -1 --pretty=format:"%an %ae %at" "$rev"
41}
42
43test_expect_success 'setup' '
44	cat >message <<-EOF &&
45	amend! B
46	$EMPTY
47	new subject
48	$EMPTY
49	new
50	body
51	EOF
52
53	test_commit A A &&
54	test_commit B B &&
55	get_author HEAD >expected-author &&
56	ORIG_AUTHOR_NAME="$GIT_AUTHOR_NAME" &&
57	ORIG_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" &&
58	GIT_AUTHOR_NAME="Amend Author" &&
59	GIT_AUTHOR_EMAIL="amend@example.com" &&
60	test_commit "$(cat message)" A A1 A1 &&
61	test_commit A2 A &&
62	test_commit A3 A &&
63	GIT_AUTHOR_NAME="$ORIG_AUTHOR_NAME" &&
64	GIT_AUTHOR_EMAIL="$ORIG_AUTHOR_EMAIL" &&
65	git checkout -b conflicts-branch A &&
66	test_commit conflicts A &&
67
68	set_fake_editor &&
69	git checkout -b branch B &&
70	echo B1 >B &&
71	test_tick &&
72	git commit --fixup=HEAD -a &&
73	git tag B1 &&
74	test_tick &&
75	FAKE_COMMIT_AMEND="edited 1" git commit --fixup=reword:B &&
76	test_tick &&
77	FAKE_COMMIT_AMEND="edited 2" git commit --fixup=reword:HEAD &&
78	echo B2 >B &&
79	test_tick &&
80	FAKE_COMMIT_AMEND="edited squash" git commit --squash=HEAD -a &&
81	git tag B2 &&
82	echo B3 >B &&
83	test_tick &&
84	FAKE_COMMIT_AMEND="edited 3" git commit -a --fixup=amend:HEAD^ &&
85	git tag B3 &&
86
87	GIT_AUTHOR_NAME="Rebase Author" &&
88	GIT_AUTHOR_EMAIL="rebase.author@example.com" &&
89	GIT_COMMITTER_NAME="Rebase Committer" &&
90	GIT_COMMITTER_EMAIL="rebase.committer@example.com"
91'
92
93test_expect_success 'simple fixup -C works' '
94	test_when_finished "test_might_fail git rebase --abort" &&
95	git checkout --detach A2 &&
96	FAKE_LINES="1 fixup_-C 2" git rebase -i B &&
97	test_cmp_rev HEAD^ B &&
98	test_cmp_rev HEAD^{tree} A2^{tree} &&
99	test_commit_message HEAD -m "A2"
100'
101
102test_expect_success 'simple fixup -c works' '
103	test_when_finished "test_might_fail git rebase --abort" &&
104	git checkout --detach A2 &&
105	git log -1 --pretty=format:%B >expected-fixup-message &&
106	test_write_lines "" "Modified A2" >>expected-fixup-message &&
107	FAKE_LINES="1 fixup_-c 2" \
108		FAKE_COMMIT_AMEND="Modified A2" \
109		git rebase -i B &&
110	test_cmp_rev HEAD^ B &&
111	test_cmp_rev HEAD^{tree} A2^{tree} &&
112	test_commit_message HEAD expected-fixup-message
113'
114
115test_expect_success 'fixup -C removes amend! from message' '
116	test_when_finished "test_might_fail git rebase --abort" &&
117	git checkout --detach A1 &&
118	git log -1 --pretty=format:%b >expected-message &&
119	FAKE_LINES="1 fixup_-C 2" git rebase -i A &&
120	test_cmp_rev HEAD^ A &&
121	test_cmp_rev HEAD^{tree} A1^{tree} &&
122	test_commit_message HEAD expected-message &&
123	get_author HEAD >actual-author &&
124	test_cmp expected-author actual-author
125'
126
127test_expect_success 'fixup -C with conflicts gives correct message' '
128	test_when_finished "test_might_fail git rebase --abort" &&
129	git checkout --detach A1 &&
130	git log -1 --pretty=format:%b >expected-message &&
131	test_write_lines "" "edited" >>expected-message &&
132	test_must_fail env FAKE_LINES="1 fixup_-C 2" git rebase -i conflicts &&
133	git checkout --theirs -- A &&
134	git add A &&
135	FAKE_COMMIT_AMEND=edited git rebase --continue &&
136	test_cmp_rev HEAD^ conflicts &&
137	test_cmp_rev HEAD^{tree} A1^{tree} &&
138	test_commit_message HEAD expected-message &&
139	get_author HEAD >actual-author &&
140	test_cmp expected-author actual-author
141'
142
143test_expect_success 'skipping fixup -C after fixup gives correct message' '
144	test_when_finished "test_might_fail git rebase --abort" &&
145	git checkout --detach A3 &&
146	test_must_fail env FAKE_LINES="1 fixup 2 fixup_-C 4" git rebase -i A &&
147	git reset --hard &&
148	FAKE_COMMIT_AMEND=edited git rebase --continue &&
149	test_commit_message HEAD -m "B"
150'
151
152test_expect_success 'sequence of fixup, fixup -C & squash --signoff works' '
153	git checkout --detach B3 &&
154	FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4 squash 5 fixup_-C 6" \
155		FAKE_COMMIT_AMEND=squashed \
156		FAKE_MESSAGE_COPY=actual-squash-message \
157		git -c commit.status=false rebase -ik --signoff A &&
158	git diff-tree --exit-code --patch HEAD B3 -- &&
159	test_cmp_rev HEAD^ A &&
160	test_cmp "$TEST_DIRECTORY/t3437/expected-squash-message" \
161		actual-squash-message
162'
163
164test_expect_success 'first fixup -C commented out in sequence fixup fixup -C fixup -C' '
165	test_when_finished "test_might_fail git rebase --abort" &&
166	git checkout --detach B2~ &&
167	git log -1 --pretty=format:%b >expected-message &&
168	FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4" git rebase -i A &&
169	test_cmp_rev HEAD^ A &&
170	test_commit_message HEAD expected-message
171'
172
173test_expect_success 'multiple fixup -c opens editor once' '
174	test_when_finished "test_might_fail git rebase --abort" &&
175	git checkout --detach A3 &&
176	git log -1 --pretty=format:%B >expected-message &&
177	test_write_lines "" "Modified-A3" >>expected-message &&
178	FAKE_COMMIT_AMEND="Modified-A3" \
179		FAKE_LINES="1 fixup_-C 2 fixup_-c 3 fixup_-c 4" \
180		EXPECT_HEADER_COUNT=4 \
181		git rebase -i A &&
182	test_cmp_rev HEAD^ A &&
183	get_author HEAD >actual-author &&
184	test_cmp expected-author actual-author &&
185	test_commit_message HEAD expected-message
186'
187
188test_expect_success 'sequence squash, fixup & fixup -c gives combined message' '
189	test_when_finished "test_might_fail git rebase --abort" &&
190	git checkout --detach A3 &&
191	FAKE_LINES="1 squash 2 fixup 3 fixup_-c 4" \
192		FAKE_MESSAGE_COPY=actual-combined-message \
193		git -c commit.status=false rebase -i A &&
194	test_cmp "$TEST_DIRECTORY/t3437/expected-combined-message" \
195		actual-combined-message &&
196	test_cmp_rev HEAD^ A
197'
198
199test_expect_success 'fixup -C works upon --autosquash with amend!' '
200	git checkout --detach B3 &&
201	FAKE_COMMIT_AMEND=squashed \
202		FAKE_MESSAGE_COPY=actual-squash-message \
203		git -c commit.status=false rebase -ik --autosquash \
204						--signoff A &&
205	git diff-tree --exit-code --patch HEAD B3 -- &&
206	test_cmp_rev HEAD^ A &&
207	test_cmp "$TEST_DIRECTORY/t3437/expected-squash-message" \
208		actual-squash-message
209'
210
211test_done
212