Skip to content

Commit 54f98fe

Browse files
committed
checkout/restore: refuse unmerging paths unless checking out of the index
Recreating unmerged index entries using resolve-undo data, recreating conflicted working tree files using unmerged index entries, and writing data out of unmerged index entries, make sense only when we are checking paths out of the index and not when we are checking paths out of a tree-ish. Add an extra check to make sure "--merge" and "--ours/--theirs" options are rejected when checking out from a tree-ish, update the document (especially the SYNOPSIS section) to highlight that they are incompatible, and add a few tests to make sure the combination fails. Signed-off-by: Junio C Hamano <[email protected]>
1 parent c0a4ae7 commit 54f98fe

File tree

5 files changed

+29
-5
lines changed

5 files changed

+29
-5
lines changed

Documentation/git-checkout.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ SYNOPSIS
1212
'git checkout' [-q] [-f] [-m] --detach [<branch>]
1313
'git checkout' [-q] [-f] [-m] [--detach] <commit>
1414
'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>]
15-
'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...
16-
'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]
15+
'git checkout' [-f] <tree-ish> [--] <pathspec>...
16+
'git checkout' [-f] <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul]
17+
'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>...
18+
'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul]
1719
'git checkout' (-p|--patch) [<tree-ish>] [--] [<pathspec>...]
1820

1921
DESCRIPTION
@@ -260,7 +262,8 @@ and mark the resolved paths with `git add` (or `git rm` if the merge
260262
should result in deletion of the path).
261263
+
262264
When checking out paths from the index, this option lets you recreate
263-
the conflicted merge in the specified paths.
265+
the conflicted merge in the specified paths. This option cannot be
266+
used when checking out paths from a tree-ish.
264267
+
265268
When switching branches with `--merge`, staged changes may be lost.
266269

Documentation/git-restore.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ all modified paths.
7878
--theirs::
7979
When restoring files in the working tree from the index, use
8080
stage #2 ('ours') or #3 ('theirs') for unmerged paths.
81+
This option cannot be used when checking out paths from a
82+
tree-ish (i.e. with the `--source` option).
8183
+
8284
Note that during `git rebase` and `git pull --rebase`, 'ours' and
8385
'theirs' may appear swapped. See the explanation of the same options
@@ -87,6 +89,8 @@ in linkgit:git-checkout[1] for details.
8789
--merge::
8890
When restoring files on the working tree from the index,
8991
recreate the conflicted merge in the unmerged paths.
92+
This option cannot be used when checking out paths from a
93+
tree-ish (i.e. with the `--source` option).
9094

9195
--conflict=<style>::
9296
The same as `--merge` option above, but changes the way the

builtin/checkout.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,15 @@ static int checkout_paths(const struct checkout_opts *opts,
520520
"--merge", "--conflict", "--staged");
521521
}
522522

523+
/*
524+
* recreating unmerged index entries and writing out data from
525+
* unmerged index entries would make no sense when checking out
526+
* of a tree-ish.
527+
*/
528+
if ((opts->merge || opts->writeout_stage) && opts->source_tree)
529+
die(_("'%s', '%s', or '%s' cannot be used when checking out of a tree"),
530+
"--merge", "--ours", "--theirs");
531+
523532
if (opts->patch_mode) {
524533
enum add_p_mode patch_mode;
525534
const char *rev = new_branch_info->name;

t/t2070-restore.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,22 @@ test_expect_success 'restore --staged invalidates cache tree for deletions' '
137137
test_must_fail git rev-parse HEAD:new1
138138
'
139139

140-
test_expect_success 'restore with merge options rejects --staged' '
140+
test_expect_success 'restore with merge options are incompatible with certain options' '
141141
for opts in \
142142
"--staged --ours" \
143143
"--staged --theirs" \
144144
"--staged --merge" \
145+
"--source=HEAD --ours" \
146+
"--source=HEAD --theirs" \
147+
"--source=HEAD --merge" \
145148
"--staged --conflict=diff3" \
146149
"--staged --worktree --ours" \
147150
"--staged --worktree --theirs" \
148151
"--staged --worktree --merge" \
149152
"--staged --worktree --conflict=zdiff3"
150153
do
151154
test_must_fail git restore $opts . 2>err &&
152-
grep "cannot be used with --staged" err || return
155+
grep "cannot be used" err || return
153156
done
154157
'
155158

t/t7201-co.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,11 @@ test_expect_success 'checkout unmerged stage' '
497497
test ztheirside = "z$(cat file)"
498498
'
499499

500+
test_expect_success 'checkout path with --merge from tree-ish is a no-no' '
501+
setup_conflicting_index &&
502+
test_must_fail git checkout -m HEAD -- file
503+
'
504+
500505
test_expect_success 'checkout with --merge' '
501506
setup_conflicting_index &&
502507
echo "none of the above" >sample &&

0 commit comments

Comments
 (0)