Re: Possible regression: overwriting untracked files in a fresh repo

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



reset_tree() is used from two places in checkout.

 (1) When --force is given, to reset potentially unmerged state away and
     forcibly switch to the destination branch.  We do an equivalent of
     "reset --hard";

 (2) When switching from a dirty work tree using --merge, we first write
     out the current index + any local changes in the work tree as a tree
     object (thus ensuring that the index is merged at this point), and
     then switch forcibly to the new branch by calling the function.

     After switching to the new branch, we merge the difference between
     the old commit and the tree that represents the dirty work tree,
     but then reset the index to the new branch.

The "checking out a real branch from an unborn branch" codepath was
reusing codepath for (1), essentially doing "reset --hard new".  This of
course allows any work tree cruft that gets in the way removed.

The patch changes it not to force, but adds another call style for the
reset_tree() function that does not do the hard reset, and uses it when
you are switching from an unborn branch (or a broken one).

I do not think that this is the correct fix, but it should be a good start
for other people to take a look at the issue.  With this change, any
leftover work tree files will remain, but it has an interesting effect.

    $ git checkout maint
    $ echo 'ref: refs/heads/nosuch' >.git/HEAD
    $ git checkout -b foo master

You will notice that the index matches master (as expected), but the work
tree mostly matches maint.  Knowing what these files are (i.e. "these are
git.git source files that match 'maint' branch, and are vastly behind what
are in 'master' branch we are switching to"), this result is utterly
counterintuitive and feels wrong, but if you consider a case like what
Dscho brought up originally in the thread of having a freshly initialized
empty repository with some uncommitted files, totally unrelated to what
you are checking out, I think you could argue that it is the right thing.

I dunno.

 builtin-checkout.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/builtin-checkout.c b/builtin-checkout.c
index 8a9a474..2930bd6 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -309,16 +309,17 @@ static void describe_detached_head(char *msg, struct commit *commit)
 	strbuf_release(&sb);
 }
 
-static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)
+static int reset_tree(struct tree *tree, struct checkout_opts *o, int flags)
 {
 	struct unpack_trees_options opts;
 	struct tree_desc tree_desc;
+	int worktree = !!(flags & 01);
 
 	memset(&opts, 0, sizeof(opts));
 	opts.head_idx = -1;
 	opts.update = worktree;
 	opts.skip_unmerged = !worktree;
-	opts.reset = 1;
+	opts.reset = !(flags & 02);
 	opts.merge = 1;
 	opts.fn = oneway_merge;
 	opts.verbose_update = !o->quiet;
@@ -373,6 +374,10 @@ static int merge_working_tree(struct checkout_opts *opts,
 		ret = reset_tree(new->commit->tree, opts, 1);
 		if (ret)
 			return ret;
+	} else if (!old->commit) {
+		ret = reset_tree(new->commit->tree, opts, 2);
+		if (ret)
+			return ret;
 	} else {
 		struct tree_desc trees[2];
 		struct tree *tree;
@@ -542,11 +547,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 	}
 
 	if (!old.commit && !opts->force) {
-		if (!opts->quiet) {
+		if (!opts->quiet)
 			warning("You appear to be on a branch yet to be born.");
-			warning("Forcing checkout of %s.", new->name);
-		}
-		opts->force = 1;
 	}
 
 	ret = merge_working_tree(opts, &old, new);
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]