pull: abort by default when fast-forwarding is not possible

We have for some time shown a long warning when the user does not specify how to reconcile divergent branches with git pull. Make it an error now. Initial-patch-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Jul 22, 2021 at 05:04 UTC 031e2f7ae195069d00d21cde906fce5b0318dbdd
13 files changed +84 -78
Documentation/git-pull.txt
+12 -8
@@ -15,14 +15,18 @@ SYNOPSIS
15 DESCRIPTION
16 -----------
17
18 -Incorporates changes from a remote repository into the current
19 -branch. In its default mode, `git pull` is shorthand for
20 -`git fetch` followed by `git merge FETCH_HEAD`.
21 -
22 -More precisely, 'git pull' runs 'git fetch' with the given
23 -parameters and calls 'git merge' to merge the retrieved branch
24 -heads into the current branch.
25 -With `--rebase`, it runs 'git rebase' instead of 'git merge'.
18 +Incorporates changes from a remote repository into the current branch.
19 +If the current branch is behind the remote, then by default it will
20 +fast-forward the current branch to match the remote. If the current
21 +branch and the remote have diverged, the user needs to specify how to
22 +reconcile the divergent branches with `--no-ff`, `--ff`, or `--rebase`
23 +(or the corresponding configuration options in `pull.ff` or
24 +`pull.rebase`).
25 +
26 +More precisely, `git pull` runs `git fetch` with the given parameters
27 +and then depending on configuration options or command line flags,
28 +will call either `git merge` or `git rebase` to reconcile diverging
29 +branches.
30
31 <repository> should be the name of a remote repository as
32 passed to linkgit:git-fetch[1]. <refspec> can name an
builtin/pull.c
+6 -4
@@ -927,9 +927,9 @@ static int get_can_ff(struct object_id *orig_head, struct object_id *orig_merge_
927
928 static void show_advice_pull_non_ff(void)
929 {
930 - advise(_("Pulling without specifying how to reconcile divergent branches is\n"
931 - "discouraged. You can squelch this message by running one of the following\n"
932 - "commands sometime before your next pull:\n"
930 + advise(_("You have divergent branches and need to specify how to reconcile them.\n"
931 + "You can do so by running one of the following commands sometime before\n"
932 + "your next pull:\n"
933 "\n"
934 " git config pull.rebase false # merge (the default strategy)\n"
935 " git config pull.rebase true # rebase\n"
@@ -1067,8 +1067,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
1067 opt_rebase = REBASE_FALSE;
1068 }
1069 /* If no action specified and we can't fast forward, then warn. */
1070 - if (!opt_ff && rebase_unspecified && !can_ff)
1070 + if (!opt_ff && rebase_unspecified && !can_ff) {
1071 show_advice_pull_non_ff();
1072 + die(_("Need to specify how to reconcile divergent branches."));
1073 + }
1074
1075 if (opt_rebase) {
1076 int ret = 0;
t/t4013-diff-various.sh
+1 -1
@@ -65,7 +65,7 @@ test_expect_success setup '
65 export GIT_AUTHOR_DATE GIT_COMMITTER_DATE &&
66
67 git checkout master &&
68 - git pull -s ours . side &&
68 + git pull -s ours --no-rebase . side &&
69
70 GIT_AUTHOR_DATE="2006-06-26 00:05:00 +0000" &&
71 GIT_COMMITTER_DATE="2006-06-26 00:05:00 +0000" &&
t/t5520-pull.sh
+10 -10
@@ -136,12 +136,12 @@ test_expect_success 'the default remote . should not break explicit pull' '
136 git reset --hard HEAD^ &&
137 echo file >expect &&
138 test_cmp expect file &&
139 - git pull . second &&
139 + git pull --no-rebase . second &&
140 echo modified >expect &&
141 test_cmp expect file &&
142 git reflog -1 >reflog.actual &&
143 sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
144 - echo "OBJID HEAD@{0}: pull . second: Fast-forward" >reflog.expected &&
144 + echo "OBJID HEAD@{0}: pull --no-rebase . second: Fast-forward" >reflog.expected &&
145 test_cmp reflog.expected reflog.fuzzy
146 '
147
@@ -226,7 +226,7 @@ test_expect_success 'fail if the index has unresolved entries' '
226 test_commit modified2 file &&
227 git ls-files -u >unmerged &&
228 test_must_be_empty unmerged &&
229 - test_must_fail git pull . second &&
229 + test_must_fail git pull --no-rebase . second &&
230 git ls-files -u >unmerged &&
231 test_file_not_empty unmerged &&
232 cp file expected &&
@@ -409,37 +409,37 @@ test_expect_success 'pull --rebase --no-autostash & rebase.autostash unset' '
409
410 test_expect_success 'pull succeeds with dirty working directory and merge.autostash set' '
411 test_config merge.autostash true &&
412 - test_pull_autostash 2
412 + test_pull_autostash 2 --no-rebase
413 '
414
415 test_expect_success 'pull --autostash & merge.autostash=true' '
416 test_config merge.autostash true &&
417 - test_pull_autostash 2 --autostash
417 + test_pull_autostash 2 --autostash --no-rebase
418 '
419
420 test_expect_success 'pull --autostash & merge.autostash=false' '
421 test_config merge.autostash false &&
422 - test_pull_autostash 2 --autostash
422 + test_pull_autostash 2 --autostash --no-rebase
423 '
424
425 test_expect_success 'pull --autostash & merge.autostash unset' '
426 test_unconfig merge.autostash &&
427 - test_pull_autostash 2 --autostash
427 + test_pull_autostash 2 --autostash --no-rebase
428 '
429
430 test_expect_success 'pull --no-autostash & merge.autostash=true' '
431 test_config merge.autostash true &&
432 - test_pull_autostash_fail --no-autostash
432 + test_pull_autostash_fail --no-autostash --no-rebase
433 '
434
435 test_expect_success 'pull --no-autostash & merge.autostash=false' '
436 test_config merge.autostash false &&
437 - test_pull_autostash_fail --no-autostash
437 + test_pull_autostash_fail --no-autostash --no-rebase
438 '
439
440 test_expect_success 'pull --no-autostash & merge.autostash unset' '
441 test_unconfig merge.autostash &&
442 - test_pull_autostash_fail --no-autostash
442 + test_pull_autostash_fail --no-autostash --no-rebase
443 '
444
445 test_expect_success 'pull.rebase' '
t/t5521-pull-options.sh
+2 -2
@@ -113,7 +113,7 @@ test_expect_success 'git pull --force' '
113 git pull two &&
114 test_commit A &&
115 git branch -f origin &&
116 - git pull --all --force
116 + git pull --no-rebase --all --force
117 )
118 '
119
@@ -179,7 +179,7 @@ test_expect_success 'git pull --allow-unrelated-histories' '
179 (
180 cd dst &&
181 test_must_fail git pull ../src side &&
182 - git pull --allow-unrelated-histories ../src side
182 + git pull --no-rebase --allow-unrelated-histories ../src side
183 )
184 '
185
t/t5524-pull-msg.sh
+2 -2
@@ -28,7 +28,7 @@ test_expect_success setup '
28 test_expect_success pull '
29 (
30 cd cloned &&
31 - git pull --log &&
31 + git pull --no-rebase --log &&
32 git log -2 &&
33 git cat-file commit HEAD >result &&
34 grep Dollar result
@@ -41,7 +41,7 @@ test_expect_success '--log=1 limits shortlog length' '
41 git reset --hard HEAD^ &&
42 test "$(cat afile)" = original &&
43 test "$(cat bfile)" = added &&
44 - git pull --log=1 &&
44 + git pull --no-rebase --log=1 &&
45 git log -3 &&
46 git cat-file commit HEAD >result &&
47 grep Dollar result &&
t/t5553-set-upstream.sh
+7 -7
@@ -108,27 +108,27 @@ test_expect_success 'setup commit on main and other pull' '
108
109 test_expect_success 'pull --set-upstream upstream main sets branch main but not other' '
110 clear_config main other &&
111 - git pull --set-upstream upstream main &&
111 + git pull --no-rebase --set-upstream upstream main &&
112 check_config main upstream refs/heads/main &&
113 check_config_missing other
114 '
115
116 test_expect_success 'pull --set-upstream main:other2 does not set the branch other2' '
117 clear_config other2 &&
118 - git pull --set-upstream upstream main:other2 &&
118 + git pull --no-rebase --set-upstream upstream main:other2 &&
119 check_config_missing other2
120 '
121
122 test_expect_success 'pull --set-upstream upstream other sets branch main' '
123 clear_config main other &&
124 - git pull --set-upstream upstream other &&
124 + git pull --no-rebase --set-upstream upstream other &&
125 check_config main upstream refs/heads/other &&
126 check_config_missing other
127 '
128
129 test_expect_success 'pull --set-upstream upstream tag does not set the tag' '
130 clear_config three &&
131 - git pull --tags --set-upstream upstream three &&
131 + git pull --no-rebase --tags --set-upstream upstream three &&
132 check_config_missing three
133 '
134
@@ -144,16 +144,16 @@ test_expect_success 'pull --set-upstream http://nosuchdomain.example.com fails w
144
145 test_expect_success 'pull --set-upstream upstream HEAD sets branch HEAD' '
146 clear_config main other &&
147 - git pull --set-upstream upstream HEAD &&
147 + git pull --no-rebase --set-upstream upstream HEAD &&
148 check_config main upstream HEAD &&
149 git checkout other &&
150 - git pull --set-upstream upstream HEAD &&
150 + git pull --no-rebase --set-upstream upstream HEAD &&
151 check_config other upstream HEAD
152 '
153
154 test_expect_success 'pull --set-upstream upstream with more than one branch does nothing' '
155 clear_config main three &&
156 - git pull --set-upstream upstream main three &&
156 + git pull --no-rebase --set-upstream upstream main three &&
157 check_config_missing main &&
158 check_config_missing three
159 '
t/t5604-clone-reference.sh
+2 -2
@@ -87,7 +87,7 @@ test_expect_success 'updating origin' '
87 '
88
89 test_expect_success 'pulling changes from origin' '
90 - git -C C pull origin
90 + git -C C pull --no-rebase origin
91 '
92
93 # the 2 local objects are commit and tree from the merge
@@ -96,7 +96,7 @@ test_expect_success 'that alternate to origin gets used' '
96 '
97
98 test_expect_success 'pulling changes from origin' '
99 - git -C D pull origin
99 + git -C D pull --no-rebase origin
100 '
101
102 # the 5 local objects are expected; file3 blob, commit in A to add it
t/t6402-merge-rename.sh
+9 -9
@@ -103,7 +103,7 @@ test_expect_success 'setup' '
103 test_expect_success 'pull renaming branch into unrenaming one' \
104 '
105 git show-branch &&
106 - test_expect_code 1 git pull . white &&
106 + test_expect_code 1 git pull --no-rebase . white &&
107 git ls-files -s &&
108 git ls-files -u B >b.stages &&
109 test_line_count = 3 b.stages &&
@@ -121,7 +121,7 @@ test_expect_success 'pull renaming branch into another renaming one' \
121 rm -f B &&
122 git reset --hard &&
123 git checkout red &&
124 - test_expect_code 1 git pull . white &&
124 + test_expect_code 1 git pull --no-rebase . white &&
125 git ls-files -u B >b.stages &&
126 test_line_count = 3 b.stages &&
127 git ls-files -s N >n.stages &&
@@ -137,7 +137,7 @@ test_expect_success 'pull unrenaming branch into renaming one' \
137 '
138 git reset --hard &&
139 git show-branch &&
140 - test_expect_code 1 git pull . main &&
140 + test_expect_code 1 git pull --no-rebase . main &&
141 git ls-files -u B >b.stages &&
142 test_line_count = 3 b.stages &&
143 git ls-files -s N >n.stages &&
@@ -153,7 +153,7 @@ test_expect_success 'pull conflicting renames' \
153 '
154 git reset --hard &&
155 git show-branch &&
156 - test_expect_code 1 git pull . blue &&
156 + test_expect_code 1 git pull --no-rebase . blue &&
157 git ls-files -u A >a.stages &&
158 test_line_count = 1 a.stages &&
159 git ls-files -u B >b.stages &&
@@ -173,7 +173,7 @@ test_expect_success 'interference with untracked working tree file' '
173 git reset --hard &&
174 git show-branch &&
175 echo >A this file should not matter &&
176 - test_expect_code 1 git pull . white &&
176 + test_expect_code 1 git pull --no-rebase . white &&
177 test_path_is_file A
178 '
179
@@ -183,7 +183,7 @@ test_expect_success 'interference with untracked working tree file' '
183 git show-branch &&
184 rm -f A &&
185 echo >A this file should not matter &&
186 - test_expect_code 1 git pull . red &&
186 + test_expect_code 1 git pull --no-rebase . red &&
187 test_path_is_file A
188 '
189
@@ -193,7 +193,7 @@ test_expect_success 'interference with untracked working tree file' '
193 git checkout -f main &&
194 git tag -f anchor &&
195 git show-branch &&
196 - git pull . yellow &&
196 + git pull --no-rebase . yellow &&
197 test_path_is_missing M &&
198 git reset --hard anchor
199 '
@@ -220,7 +220,7 @@ test_expect_success 'updated working tree file should prevent the merge' '
220 echo >>M one line addition &&
221 cat M >M.saved &&
222 git update-index M &&
223 - test_expect_code 128 git pull . yellow &&
223 + test_expect_code 128 git pull --no-rebase . yellow &&
224 test_cmp M M.saved &&
225 rm -f M.saved
226 '
@@ -232,7 +232,7 @@ test_expect_success 'interference with untracked working tree file' '
232 git tag -f anchor &&
233 git show-branch &&
234 echo >M this file should not matter &&
235 - git pull . main &&
235 + git pull --no-rebase . main &&
236 test_path_is_file M &&
237 ! {
238 git ls-files -s |
t/t6409-merge-subtree.sh
+3 -3
@@ -100,7 +100,7 @@ test_expect_success 'merge update' '
100 git checkout -b topic_2 &&
101 git commit -m "update git-gui" &&
102 cd ../git &&
103 - git pull -s subtree gui topic_2 &&
103 + git pull --no-rebase -s subtree gui topic_2 &&
104 git ls-files -s >actual &&
105 (
106 echo "100644 $o3 0 git-gui/git-gui.sh" &&
@@ -129,7 +129,7 @@ test_expect_success 'initial ambiguous subtree' '
129 test_expect_success 'merge using explicit' '
130 cd ../git &&
131 git reset --hard topic_2 &&
132 - git pull -Xsubtree=git-gui gui topic_2 &&
132 + git pull --no-rebase -Xsubtree=git-gui gui topic_2 &&
133 git ls-files -s >actual &&
134 (
135 echo "100644 $o3 0 git-gui/git-gui.sh" &&
@@ -142,7 +142,7 @@ test_expect_success 'merge using explicit' '
142 test_expect_success 'merge2 using explicit' '
143 cd ../git &&
144 git reset --hard topic_2 &&
145 - git pull -Xsubtree=git-gui2 gui topic_2 &&
145 + git pull --no-rebase -Xsubtree=git-gui2 gui topic_2 &&
146 git ls-files -s >actual &&
147 (
148 echo "100644 $o1 0 git-gui/git-gui.sh" &&
t/t6417-merge-ours-theirs.sh
+5 -5
@@ -69,11 +69,11 @@ test_expect_success 'binary file with -Xours/-Xtheirs' '
69 '
70
71 test_expect_success 'pull passes -X to underlying merge' '
72 - git reset --hard main && git pull -s recursive -Xours . side &&
73 - git reset --hard main && git pull -s recursive -X ours . side &&
74 - git reset --hard main && git pull -s recursive -Xtheirs . side &&
75 - git reset --hard main && git pull -s recursive -X theirs . side &&
76 - git reset --hard main && test_must_fail git pull -s recursive -X bork . side
72 + git reset --hard main && git pull --no-rebase -s recursive -Xours . side &&
73 + git reset --hard main && git pull --no-rebase -s recursive -X ours . side &&
74 + git reset --hard main && git pull --no-rebase -s recursive -Xtheirs . side &&
75 + git reset --hard main && git pull --no-rebase -s recursive -X theirs . side &&
76 + git reset --hard main && test_must_fail git pull --no-rebase -s recursive -X bork . side
77 '
78
79 test_expect_success SYMLINKS 'symlink with -Xours/-Xtheirs' '
t/t7601-merge-pull-config.sh
+24 -24
@@ -27,120 +27,120 @@ test_expect_success 'setup' '
27 git tag c3
28 '
29
30 -test_expect_success 'pull.rebase not set' '
30 +test_expect_success 'pull.rebase not set, ff possible' '
31 git reset --hard c0 &&
32 git pull . c1 2>err &&
33 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
33 + test_i18ngrep ! "You have divergent branches" err
34 '
35
36 test_expect_success 'pull.rebase not set and pull.ff=true' '
37 git reset --hard c0 &&
38 test_config pull.ff true &&
39 git pull . c1 2>err &&
40 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
40 + test_i18ngrep ! "You have divergent branches" err
41 '
42
43 test_expect_success 'pull.rebase not set and pull.ff=false' '
44 git reset --hard c0 &&
45 test_config pull.ff false &&
46 git pull . c1 2>err &&
47 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
47 + test_i18ngrep ! "You have divergent branches" err
48 '
49
50 test_expect_success 'pull.rebase not set and pull.ff=only' '
51 git reset --hard c0 &&
52 test_config pull.ff only &&
53 git pull . c1 2>err &&
54 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
54 + test_i18ngrep ! "You have divergent branches" err
55 '
56
57 test_expect_success 'pull.rebase not set and --rebase given' '
58 git reset --hard c0 &&
59 git pull --rebase . c1 2>err &&
60 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
60 + test_i18ngrep ! "You have divergent branches" err
61 '
62
63 test_expect_success 'pull.rebase not set and --no-rebase given' '
64 git reset --hard c0 &&
65 git pull --no-rebase . c1 2>err &&
66 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
66 + test_i18ngrep ! "You have divergent branches" err
67 '
68
69 test_expect_success 'pull.rebase not set and --ff given' '
70 git reset --hard c0 &&
71 git pull --ff . c1 2>err &&
72 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
72 + test_i18ngrep ! "You have divergent branches" err
73 '
74
75 test_expect_success 'pull.rebase not set and --no-ff given' '
76 git reset --hard c0 &&
77 git pull --no-ff . c1 2>err &&
78 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
78 + test_i18ngrep ! "You have divergent branches" err
79 '
80
81 test_expect_success 'pull.rebase not set and --ff-only given' '
82 git reset --hard c0 &&
83 git pull --ff-only . c1 2>err &&
84 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
84 + test_i18ngrep ! "You have divergent branches" err
85 '
86
87 test_expect_success 'pull.rebase not set (not-fast-forward)' '
88 git reset --hard c2 &&
89 - git -c color.advice=always pull . c1 2>err &&
89 + test_must_fail git -c color.advice=always pull . c1 2>err &&
90 test_decode_color <err >decoded &&
91 test_i18ngrep "<YELLOW>hint: " decoded &&
92 - test_i18ngrep "Pulling without specifying how to reconcile" decoded
92 + test_i18ngrep "You have divergent branches" decoded
93 '
94
95 test_expect_success 'pull.rebase not set and pull.ff=true (not-fast-forward)' '
96 git reset --hard c2 &&
97 test_config pull.ff true &&
98 git pull . c1 2>err &&
99 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
99 + test_i18ngrep ! "You have divergent branches" err
100 '
101
102 test_expect_success 'pull.rebase not set and pull.ff=false (not-fast-forward)' '
103 git reset --hard c2 &&
104 test_config pull.ff false &&
105 git pull . c1 2>err &&
106 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
106 + test_i18ngrep ! "You have divergent branches" err
107 '
108
109 test_expect_success 'pull.rebase not set and pull.ff=only (not-fast-forward)' '
110 git reset --hard c2 &&
111 test_config pull.ff only &&
112 test_must_fail git pull . c1 2>err &&
113 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
113 + test_i18ngrep ! "You have divergent branches" err
114 '
115
116 test_expect_success 'pull.rebase not set and --rebase given (not-fast-forward)' '
117 git reset --hard c2 &&
118 git pull --rebase . c1 2>err &&
119 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
119 + test_i18ngrep ! "You have divergent branches" err
120 '
121
122 test_expect_success 'pull.rebase not set and --no-rebase given (not-fast-forward)' '
123 git reset --hard c2 &&
124 git pull --no-rebase . c1 2>err &&
125 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
125 + test_i18ngrep ! "You have divergent branches" err
126 '
127
128 test_expect_success 'pull.rebase not set and --ff given (not-fast-forward)' '
129 git reset --hard c2 &&
130 git pull --ff . c1 2>err &&
131 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
131 + test_i18ngrep ! "You have divergent branches" err
132 '
133
134 test_expect_success 'pull.rebase not set and --no-ff given (not-fast-forward)' '
135 git reset --hard c2 &&
136 git pull --no-ff . c1 2>err &&
137 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
137 + test_i18ngrep ! "You have divergent branches" err
138 '
139
140 test_expect_success 'pull.rebase not set and --ff-only given (not-fast-forward)' '
141 git reset --hard c2 &&
142 test_must_fail git pull --ff-only . c1 2>err &&
143 - test_i18ngrep ! "Pulling without specifying how to reconcile" err
143 + test_i18ngrep ! "You have divergent branches" err
144 '
145
146 test_does_rebase () {
@@ -325,16 +325,16 @@ test_expect_success 'pull.rebase=false and --ff, ff not possible' '
325
326 # End of groupings for conflicting merge vs. rebase flags/options
327
328 -test_expect_failure 'Multiple heads warns about inability to fast forward' '
328 +test_expect_success 'Multiple heads warns about inability to fast forward' '
329 git reset --hard c1 &&
330 test_must_fail git pull . c2 c3 2>err &&
331 - test_i18ngrep "Pulling without specifying how to reconcile" err
331 + test_i18ngrep "You have divergent branches" err
332 '
333
334 test_expect_failure 'Multiple can never be fast forwarded' '
335 git reset --hard c0 &&
336 test_must_fail git -c pull.ff=only pull . c1 c2 c3 2>err &&
337 - test_i18ngrep ! "Pulling without specifying how to reconcile" err &&
337 + test_i18ngrep ! "You have divergent branches" err &&
338 # In addition to calling out "cannot fast-forward", we very much
339 # want the "multiple branches" piece to be called out to users.
340 test_i18ngrep "Cannot fast-forward to multiple branches" err
@@ -343,7 +343,7 @@ test_expect_failure 'Multiple can never be fast forwarded' '
343 test_expect_success 'Cannot rebase with multiple heads' '
344 git reset --hard c0 &&
345 test_must_fail git -c pull.rebase=true pull . c1 c2 c3 2>err &&
346 - test_i18ngrep ! "Pulling without specifying how to reconcile" err &&
346 + test_i18ngrep ! "You have divergent branches" err &&
347 test_i18ngrep "Cannot rebase onto multiple branches." err
348 '
349
t/t7603-merge-reduce-heads.sh
+1 -1
@@ -68,7 +68,7 @@ test_expect_success 'merge c1 with c2, c3, c4, c5' '
68
69 test_expect_success 'pull c2, c3, c4, c5 into c1' '
70 git reset --hard c1 &&
71 - git pull . c2 c3 c4 c5 &&
71 + git pull --no-rebase . c2 c3 c4 c5 &&
72 test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
73 test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
74 test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&