Commit 291d823e authored by Junio C Hamano's avatar Junio C Hamano

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: default avatarJunio C Hamano <>
parent 2e2b887d
......@@ -155,6 +155,7 @@ struct checkout_opts {
int quiet;
int merge;
int force;
int writeout_error;
char *new_branch;
int new_branch_log;
......@@ -178,9 +179,20 @@ static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)
opts.dst_index = &the_index;
init_tree_desc(&tree_desc, tree->buffer, tree->size);
if (unpack_trees(1, &tree_desc, &opts))
switch (unpack_trees(1, &tree_desc, &opts)) {
case -2:
o->writeout_error = 1;
* We return 0 nevertheless, as the index is all right
* and more importantly we have made best efforts to
* update paths in the work tree, and we cannot revert
* them.
case 0:
return 0;
return 128;
return 0;
struct branch_info {
......@@ -243,7 +255,8 @@ static int merge_working_tree(struct checkout_opts *opts,
tree = parse_tree_indirect(new->commit->object.sha1);
init_tree_desc(&trees[1], tree->buffer, tree->size);
if (unpack_trees(2, trees, &topts)) {
ret = unpack_trees(2, trees, &topts);
if (ret == -1) {
* Unpack couldn't do a trivial merge; either
* 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)
update_refs_for_switch(opts, &old, new);
return post_checkout_hook(old.commit, new->commit, 1);
ret = post_checkout_hook(old.commit, new->commit, 1);
return ret || opts->writeout_error;
int cmd_checkout(int argc, const char **argv, const char *prefix)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment