Skip to content

Commit 291d823

Browse files
committed
checkout: "best effort" checkout
When unpack_trees() returned an error while switching branches, we used to stop right there, exiting without writing the index out or switching HEAD. This is Ok when unpack_trees() returned an error because it detected untracked files or locally modified paths that could be overwritten by branch switching, because that error return is done before we start to modify the work tree. But it is undesirable if unpack_trees() already started to update the work tree and a failure is returned because some but not all paths are updated in the work tree, perhaps because a directory that some files need to go in was read-only by mistake, or a file that will be overwritten by branch switching had a mandatory lock on it and we failed to unlink it. This changes the behaviour upon such an error to complete the branch switching; the files updated in the work tree will hopefully be much more consistent with the index and HEAD derived from the switched-to branch. We still issue error messages, and exit the command with non-zero status, so scripted callers need to notice it. Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 2e2b887 commit 291d823

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

builtin-checkout.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ struct checkout_opts {
155155
int quiet;
156156
int merge;
157157
int force;
158+
int writeout_error;
158159

159160
char *new_branch;
160161
int new_branch_log;
@@ -178,9 +179,20 @@ static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)
178179
opts.dst_index = &the_index;
179180
parse_tree(tree);
180181
init_tree_desc(&tree_desc, tree->buffer, tree->size);
181-
if (unpack_trees(1, &tree_desc, &opts))
182+
switch (unpack_trees(1, &tree_desc, &opts)) {
183+
case -2:
184+
o->writeout_error = 1;
185+
/*
186+
* We return 0 nevertheless, as the index is all right
187+
* and more importantly we have made best efforts to
188+
* update paths in the work tree, and we cannot revert
189+
* them.
190+
*/
191+
case 0:
192+
return 0;
193+
default:
182194
return 128;
183-
return 0;
195+
}
184196
}
185197

186198
struct branch_info {
@@ -243,7 +255,8 @@ static int merge_working_tree(struct checkout_opts *opts,
243255
tree = parse_tree_indirect(new->commit->object.sha1);
244256
init_tree_desc(&trees[1], tree->buffer, tree->size);
245257

246-
if (unpack_trees(2, trees, &topts)) {
258+
ret = unpack_trees(2, trees, &topts);
259+
if (ret == -1) {
247260
/*
248261
* Unpack couldn't do a trivial merge; either
249262
* give up or do a real merge, depending on
@@ -478,7 +491,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
478491

479492
update_refs_for_switch(opts, &old, new);
480493

481-
return post_checkout_hook(old.commit, new->commit, 1);
494+
ret = post_checkout_hook(old.commit, new->commit, 1);
495+
return ret || opts->writeout_error;
482496
}
483497

484498
int cmd_checkout(int argc, const char **argv, const char *prefix)

0 commit comments

Comments
 (0)