From: Junio C Hamano <gitster@pobox.com>
To: Jeff King <peff@peff.net>
Cc: Johannes Schindelin <Johannes.Schindelin@gmx.de>, git@vger.kernel.org
Subject: Re: Possible regression: overwriting untracked files in a fresh repo
Date: Mon, 24 Aug 2009 16:20:12 -0700 [thread overview]
Message-ID: <7vab1o3ikz.fsf@alter.siamese.dyndns.org> (raw)
In-Reply-To: <20090824190710.GB25168@coredump.intra.peff.net> (Jeff King's message of "Mon\, 24 Aug 2009 15\:07\:10 -0400")
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);
next prev parent reply other threads:[~2009-08-24 23:20 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-24 16:31 Possible regression: overwriting untracked files in a fresh repo Johannes Schindelin
2009-08-24 19:07 ` Jeff King
2009-08-24 22:39 ` Junio C Hamano
2009-08-24 23:20 ` Junio C Hamano [this message]
2009-08-25 1:36 ` Jeff King
2009-08-25 1:47 ` Jeff King
2009-08-25 2:11 ` Junio C Hamano
2009-08-25 3:03 ` Jeff King
2009-08-25 11:34 ` Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7vab1o3ikz.fsf@alter.siamese.dyndns.org \
--to=gitster@pobox.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=peff@peff.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox